26 #include <Classes.hpp>
27 #include <Controls.hpp>
28 #include <StdCtrls.hpp>
30 #include <Buttons.hpp>
31 #include <ExtCtrls.hpp>
33 #include <Dialogs.hpp>
34 #include <Graphics.hpp>
35 #include <ComCtrls.hpp>
54 #pragma package(smart_init)
73 TTrain::TTrain(
int Caller,
int RearStartElementIn,
int RearStartExitPosIn, AnsiString InputCode,
int StartSpeedIn,
int MassIn,
double MaxRunningSpeedIn,
74 double MaxBrakeRateIn,
double PowerAtRailIn,
TTrainMode TrainModeIn,
TTrainDataEntry *TrainDataEntryPtrIn,
int RepeatNumberIn,
int IncrementalMinutesIn,
75 int IncrementalDigitsIn,
int SignallerMaxSpeedIn) : RearStartElement(RearStartElementIn), RearStartExitPos(RearStartExitPosIn), HeadCode(InputCode),
76 StartSpeed(StartSpeedIn), Mass(MassIn), MaxRunningSpeed(MaxRunningSpeedIn), MaxBrakeRate(MaxBrakeRateIn), PowerAtRail(PowerAtRailIn),
77 TrainMode(TrainModeIn), TrainDataEntryPtr(TrainDataEntryPtrIn), RepeatNumber(RepeatNumberIn), IncrementalMinutes(IncrementalMinutesIn),
78 IncrementalDigits(IncrementalDigitsIn), SignallerMaxSpeed(SignallerMaxSpeedIn)
89 AnsiString(RearStartExitPosIn) +
"," + AnsiString(InputCode) +
"," + AnsiString(StartSpeedIn) +
"," + AnsiString(MassIn) +
"," +
90 AnsiString(TrainModeIn));
137 for(
int x = 0; x < 4; x++)
146 for(
int x = 0; x < 4; x++)
155 for(
int x = 0; x < 4; x++)
160 for(
int x = 0; x < 4; x++)
164 for(
int x = 0; x < 3; x++)
202 for(
int x = 0; x < 4; x++)
281 throw Exception(
"Error in attempting to delete FrontCodePtr");
285 for(
int x = 0; x < 4; x++)
289 throw Exception(
"Error in attempting to delete BackgroundPtr[" + AnsiString(x) +
"]");
294 for(
int x = 0; x < 4; x++)
298 throw Exception(
"Error in attempting to delete HeadCodeGrPtr[" + AnsiString(x) +
"]");
333 int NextElementPosition, NextEntryPos, ElementLength, SpeedLimit;
399 bool TempDerail =
false;
445 else if((NextElementPosition > -1) && (NextEntryPos > -1))
516 throw Exception(
"Error, LeadElement Exit Connection is NotSet");
526 for(
int x = 0; x < 4; x++)
533 for(
int x = 0; x < 4; x++)
800 int LockedVectorNumber;
930 AnsiString ReasonArray[24] = {
"a driver is awaited",
"a guard is awaited",
"of a medical emergency",
"of a technical problem",
"of a security issue",
931 "of a safety issue",
"of a disturbance",
"a train crew member has been taken ill",
"the driver has been taken ill",
"the guard has been taken ill",
932 "a report has been received concerning safety",
"a shoe has been lost under the train",
"of a reported theft",
933 "of an incident involving an animal",
"some luggage has been lost under the train",
"a minor repair is needed",
"a suspicious object has to be dealt with safely",
934 "a door is stuck open",
"additional stock has to be attached",
"a security alert",
"of a train fault",
"of an operating incident",
"safety checks are required",
935 "of a shortage of on train crew"};
942 if(DwellTime < TDateTime(30.0 / 86400))
944 DwellTime = TDateTime(30.0 / 86400);
946 int randval = random(10000);
951 if(randval < Utilities->MinorDelayCutoff)
958 if(randval < Utilities->ModerateDelayCutoff)
965 if(randval < Utilities->MajorDelayCutoff)
980 if(
NewDelay <
double(DwellTime) * 1440)
986 NewDelay -= double(DwellTime) * 1440;
1047 int randval2 = rand() % 24;
1048 AnsiString Reason = ReasonArray[randval2];
1051 " minutes because " + Reason);
1053 " minutes because " + Reason);
1059 " minutes because of a minor problem");
1061 " minutes because of a minor problem");
1220 if(BufferLocation ==
"")
1225 if((BufferLocation ==
"") || (BufferLocation != ExpectedLocation))
1287 int NextElementPosition, NextEntryPos;
1311 NextElementPosition = -1;
1314 if((NextElementPosition > -1) && (NextEntryPos > -1))
1459 AnsiString StationName;
1470 throw Exception(
"Error - Stopped at through station but neither lead nor mid elements have a name");
1480 if((NextElementPosition > -1) && (NextEntryPos > -1))
1628 if(TIFEntryPos == 0)
1665 if(NextElementPosition > -1)
1702 AnsiString Loc =
"";
1703 bool LocNamed =
false;
1732 Loc =
"outside railway";
1764 NextElementPosition = -1;
1775 if((NextElementPosition > -1) && (NextEntryPos > -1) && !
SPADFlag)
1793 if((NextElementPosition > -1) && (NextEntryPos > -1))
1831 FirstPair.second).
GetELink() == TempELink))
1836 SecondPair.second).
GetELink() == TempELink))
1850 FirstPair.second).
GetELink() == TempELink))
1855 SecondPair.second).
GetELink() == TempELink))
1869 FirstPair.second).
GetELink() == TempELink))
1874 SecondPair.second).
GetELink() == TempELink))
1904 ContinuationAutoSigEntry.
RouteNumber = RouteNumber;
1907 int NewLastElement = 0, NewLastExitPos = 0;
1925 if(NewLastElement == -1)
1931 if(NewLastExitPos == -1)
1935 LastElement = NewLastElement;
1936 LastExitPos = NewLastExitPos;
1939 if(CumDistance < 1200)
1945 int FirstDistance = 0;
1946 if(CumDistance >= 1200)
1948 FirstDistance = 100;
1952 FirstDistance = 1200 - CumDistance;
1954 if(FirstDistance < 100)
1956 FirstDistance = 100;
1982 if(VectorIT->RouteNumber == RouteNumber)
2019 " failed when changing aspect.\nTrains can only pass under signaller control.");
2053 LockedVectorNumber)))
2212 for(
int x = 0; x < 4; x++)
2219 for(
int x = 0; x < 4; x++)
2245 if((LeadElementTrainID > -1) && (LeadElementTrainID !=
TrainID))
2250 if(OtherTrainEntryPos == -1)
2252 throw Exception(
"Error - OtherTrainEntryPos not set");
2271 int OtherTrainID = -1;
2272 if((MidExitLinkNum == 1) || (MidExitLinkNum == 3) || (MidExitLinkNum == 7) || (MidExitLinkNum == 9))
2363 bool StopRequired =
false;
2378 int NextElementEntryPos = -1;
2379 int NextElementExitPos = -1;
2380 bool TrainOnNextElement =
false;
2381 bool StopSignalAtNextElement =
false;
2382 if(ForwardConnection)
2390 StopSignalAtNextElement = ((NextTrackElement.
Config[NextElementExitPos] ==
Signal) && (NextTrackElement.
Attribute == 0));
2392 if(TrainAtStopLinkPos1 || TrainAtStopLinkPos2 || TrainAtStopLinkPos3 || TrainAtStopLinkPos4 || (ForwardConnection && (TrainOnNextElement || StopSignalAtNextElement)))
2448 throw Exception(
"Error, Straddle shouldn't be LeadMid prior to resetting at exit from UpdateTrain");
2512 int VPos, HPos, TrainHLocLead, TrainHLocMid, TrainHLocLag, TrainVLocLead, TrainVLocMid, TrainVLocLag;
2514 bool ReturnEarly =
false;
2547 int LeftHAndOffset, TopVAndOffset;
2552 LeftHAndOffset = (TrainLead.
HLoc * 16) +
HOffset[0];
2553 if(((TrainLead.
HLoc * 16) +
HOffset[1]) < LeftHAndOffset)
2555 LeftHAndOffset = (TrainLead.
HLoc * 16) +
HOffset[1];
2557 if(((TrainMid.
HLoc * 16) +
HOffset[2]) < LeftHAndOffset)
2559 LeftHAndOffset = (TrainMid.
HLoc * 16) +
HOffset[2];
2561 if(((TrainMid.
HLoc * 16) +
HOffset[3]) < LeftHAndOffset)
2563 LeftHAndOffset = (TrainMid.
HLoc * 16) +
HOffset[3];
2565 TopVAndOffset = (TrainLead.
VLoc * 16) +
VOffset[0];
2566 if(((TrainLead.
VLoc * 16) +
VOffset[1]) < TopVAndOffset)
2568 TopVAndOffset = (TrainLead.
VLoc * 16) +
VOffset[1];
2570 if(((TrainMid.
VLoc * 16) +
VOffset[2]) < TopVAndOffset)
2572 TopVAndOffset = (TrainMid.
VLoc * 16) +
VOffset[2];
2574 if(((TrainMid.
VLoc * 16) +
VOffset[3]) < TopVAndOffset)
2576 TopVAndOffset = (TrainMid.
VLoc * 16) +
VOffset[3];
2578 HPos = LeftHAndOffset;
2579 VPos = TopVAndOffset - 10;
2583 LeftHAndOffset = (TrainLead.
HLoc * 16) +
HOffset[0];
2584 if(((TrainMid.
HLoc * 16) +
HOffset[1]) < LeftHAndOffset)
2586 LeftHAndOffset = (TrainMid.
HLoc * 16) +
HOffset[1];
2588 if(((TrainMid.
HLoc * 16) +
HOffset[2]) < LeftHAndOffset)
2590 LeftHAndOffset = (TrainMid.
HLoc * 16) +
HOffset[2];
2592 if(((TrainLag.
HLoc * 16) +
HOffset[3]) < LeftHAndOffset)
2594 LeftHAndOffset = (TrainLag.
HLoc * 16) +
HOffset[3];
2596 TopVAndOffset = (TrainLead.
VLoc * 16) +
VOffset[0];
2597 if(((TrainMid.
VLoc * 16) +
VOffset[1]) < TopVAndOffset)
2599 TopVAndOffset = (TrainMid.
VLoc * 16) +
VOffset[1];
2601 if(((TrainMid.
VLoc * 16) +
VOffset[2]) < TopVAndOffset)
2603 TopVAndOffset = (TrainMid.
VLoc * 16) +
VOffset[2];
2605 if(((TrainLag.
VLoc * 16) +
VOffset[3]) < TopVAndOffset)
2607 TopVAndOffset = (TrainLag.
VLoc * 16) +
VOffset[3];
2609 HPos = LeftHAndOffset;
2610 VPos = TopVAndOffset - 10;
2653 for(
int x = 3; x < 13; x++)
2658 for(
int y = 0; y < 54; y++)
2662 SLPtrOut[y] = SLPtrIn[y];
2663 SLPtrImage[y] = 0x01;
2687 for(
int x = 3; x < 13; x++)
2691 for(
int y = 0; y < 54; y++)
2723 Graphics::TBitmap *TempBitmap =
new Graphics::TBitmap;
2724 TempBitmap->PixelFormat = pf8bit;
2725 TempBitmap->Height = 10;
2726 TempBitmap->Width = 54;
2733 for(
int x = 0; x < 10; x++)
2735 SLPtrIn =
reinterpret_cast<Byte*
>(TempBitmap->ScanLine[x]);
2737 for(
int y = 0; y < 54; y++)
2739 if(SLPtrIn[y] == 0xac)
2743 else if(SLPtrIn[y] == 0xb4)
2747 else if(SLPtrIn[y] == 0x05)
2963 if(Code.Length() != 4)
2967 for(
int x = 1; x < 5; x++)
2974 for(
int x = 0; x < 4; x++)
3137 throw Exception(
"Error in GetOffsetValues - Link value wrong");
3150 if((EntryLink == 1) || (EntryLink == 2) || (EntryLink == 4) || (EntryLink == 7))
3165 AnsiString(
VOffset) +
"," + AnsiString(Element) +
"," + AnsiString(EntryPos) +
"," +
HeadCode);
3174 TRect SourceRect, DestRect;
3176 DestRect.init(0, 0, 8, 8);
3179 Graphics::TBitmap *TempGraphic =
new Graphics::TBitmap;
3181 TempGraphic->PixelFormat = pf8bit;
3182 TempGraphic->Width = 16;
3183 TempGraphic->Height = 16;
3189 TempGraphic->Transparent =
true;
3193 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
3194 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
3200 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3208 else if(TempElement.
SpeedTag == 89)
3212 else if(TempElement.
SpeedTag == 90)
3216 else if(TempElement.
SpeedTag == 91)
3220 else if(TempElement.
SpeedTag == 92)
3224 else if(TempElement.
SpeedTag == 93)
3228 else if(TempElement.
SpeedTag == 94)
3232 else if(TempElement.
SpeedTag == 95)
3236 TempGraphic->Transparent =
true;
3240 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
3241 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
3243 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3250 for(
int x = 0; x < 40; x++)
3265 TempGraphic->Transparent =
true;
3269 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
3270 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
3272 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3286 TempGraphic->Transparent =
true;
3290 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
3291 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
3295 TempGraphic->Canvas->Draw(0, 0, TempElement.
GraphicPtr);
3298 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3303 TempGraphic->Transparent =
true;
3307 int BDVectorPos = -1;
3316 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3321 TempGraphic->Transparent =
true;
3325 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
3326 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
3328 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3334 TempGraphic->Transparent =
true;
3338 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
3339 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
3341 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3607 throw Exception(
"Error, same train on two different bridge tracks");
3653 AnsiString(EntryPos) +
"," +
HeadCode);
3670 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in SetTrainElementID");
3689 AnsiString(EntryPos) +
"," +
HeadCode);
3698 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in ResetTrainElementID");
3731 AnsiString(ElementEntryPos) +
"," + AnsiString(
HOffset) +
"," + AnsiString(
VOffset) +
"," + AnsiString(StraddleValue) +
"," +
HeadCode);
3732 int LockedVectorNumber;
3745 TRect SourceRect, DestRect;
3746 DestRect.init(0, 0, 8, 8);
3753 int FirstELink, SecondELink = -1;
3756 if(RoutePair2.first > -1)
3765 if(SecondELink == -1)
3767 throw Exception(
"Error - Second ELink should be set but isn't in PlotAlternativeTrackRouteGraphic [1]");
3772 throw Exception(
"Error - First & Second ELinks have same value in PlotAlternativeTrackRouteGraphic");
3782 Graphics::TBitmap *DestGraphic =
new Graphics::TBitmap;
3783 DestGraphic->PixelFormat = pf8bit;
3784 DestGraphic->Width = 8;
3785 DestGraphic->Height = 8;
3786 DestGraphic->Transparent =
true;
3789 DestGraphic->Canvas->CopyRect(DestRect, RouteElement.
GetRouteEXGraphicPtr()->Canvas, SourceRect);
3798 PrefDirElement, LockedVectorNumber))
3813 if(ElementEntryPos > 1)
3835 AnsiString(EntryPos) +
"," +
HeadCode);
3837 bool WrongRoute =
false;
3863 int LinkNumber = TrackElement.
Link[EntryPos];
3864 if((LinkNumber == 1) || (LinkNumber == 3) || (LinkNumber == 7) || (LinkNumber == 9))
3869 bool LogActionErrorCalled =
false;
3879 LogActionErrorCalled =
true;
3896 else if(LinkNumber == 3)
3904 LogActionErrorCalled =
true;
3921 else if(LinkNumber == 7)
3929 LogActionErrorCalled =
true;
3946 else if(LinkNumber == 9)
3954 LogActionErrorCalled =
true;
3986 else if((RouteElement.
GetELinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3991 else if((RouteElement.
GetELinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
4001 else if((RouteElement.
GetXLinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
4006 else if((RouteElement.
GetXLinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
4015 throw Exception(
"Error, Element in route but no route found in CheckAndCancelRouteForWrongEndEntry");
4036 bool ColourError =
false, ColourError2 =
false;
4041 ColourError2 =
true;
4043 for(
int x = 0; x < 4; x++)
4048 ColourError2 =
true;
4054 "256 colours can be displayed");
4058 for(
int x = 0; x < 4; x++)
4145 AnsiString(EntryPos) +
"," +
HeadCode);
4146 int EntryHalfLength, CurrentElementHalfLength, NextElementHalfLength, CumulativeLength = 0, CurrentTrackVectorPosition = TrackVectorPosition;
4147 int DistanceAtHalfBraking, DistanceAtThreeQuarterBraking, ExitPos, NextTrackVectorPosition, NextEntryPos;
4148 bool RedSignalFlag =
false, BuffersFlag =
false, StationFlag =
false, BuffersOrContinuationNowFlag =
false, ContinuationNextFlag =
false,
4149 TrainInFrontInSignallerModeFlag =
false;
4150 double LimitingSpeed, FrontElementMaxSpeed, MaxExitSpeedAtHalfBrakingSquared, MaxExitSpeedAtHalfBraking, NextSpeedLimit, TempBrakeRate;
4151 double ExitSpeedHalfSquared, ExitSpeedFullSquared;
4152 bool SignallerStopRequired =
false;
4166 if(CurrentTrackVectorPosition > -1)
4170 if((EntryPos == 0) || (EntryPos == 2))
4183 else if(EntryPos == 1)
4207 EntryHalfLength = CurrentElementHalfLength;
4212 throw Exception(
"Error - CurrentTrackVectorPosition < 0 in SetTrainMovementValues");
4216 throw Exception(
"Error - HalfLength or SpeedLimit < 0 in SetTrainMovementValues");
4264 FrontElementMaxSpeed = LimitingSpeed;
4300 double ExitSpeedAtMaxBraking;
4305 ExitSpeedAtMaxBraking = 0;
4315 if(ExitSpeedAtMaxBraking > LimitingSpeed)
4317 SpeedToUse = ExitSpeedAtMaxBraking;
4321 SpeedToUse = LimitingSpeed;
4336 RedSignalFlag =
false;
4337 BuffersFlag =
false;
4338 StationFlag =
false;
4339 BuffersOrContinuationNowFlag =
false;
4340 ContinuationNextFlag =
false;
4343 CumulativeLength += (2 * CurrentElementHalfLength);
4346 SignallerStopRequired =
true;
4368 bool StopRequired =
false;
4384 StationFlag =
false;
4390 BuffersOrContinuationNowFlag =
true;
4392 if(!BuffersOrContinuationNowFlag && !BuffersFlag && !StationFlag)
4396 if((EntryPos == 0) || (EntryPos == 2))
4418 if(NextTrackVectorPosition > -1)
4423 if((NextEntryPos == 0) || (NextEntryPos == 2))
4436 else if(NextEntryPos == 1)
4449 if(NextEntryPos > 1)
4463 throw Exception(
"Error - Trying to access NextTrackVectorPosition when none present in SetTrainMovementValues");
4475 RedSignalFlag =
true;
4496 TrainInFrontInSignallerModeFlag =
true;
4521 if(RedSignalFlag || BuffersFlag || StationFlag || TrainInFrontInSignallerModeFlag || SignallerStopRequired ||
StepForwardFlag)
4533 double MaxHalfSpeed;
4537 if(MaxHalfSpeedAtHalfBraking > FrontElementMaxSpeed)
4539 MaxHalfSpeed = FrontElementMaxSpeed;
4543 MaxHalfSpeed = MaxHalfSpeedAtHalfBraking;
4551 bool HalfSpeedLimited =
false;
4555 HalfSpeedLimited =
true;
4585 if(HalfSpeedLimited)
4610 if(SignallerStopRequired)
4626 int TempMaxExitSpeed;
4629 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4631 MaxExitSpeedAtHalfBraking = 0;
4635 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4639 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4641 TempMaxExitSpeed = FrontElementMaxSpeed;
4645 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4657 if(ExitSpeedHalfSquared < 10)
4667 if(ExitSpeedFullSquared < 10)
4739 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4740 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4764 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4765 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4775 if(!BuffersOrContinuationNowFlag)
4777 if(NextSpeedLimit < LimitingSpeed)
4779 LimitingSpeed = NextSpeedLimit;
4783 int TempMaxExitSpeed;
4787 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4789 MaxExitSpeedAtHalfBraking = 0;
4793 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4795 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4797 TempMaxExitSpeed = FrontElementMaxSpeed;
4801 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4812 TempBrakeRate = ((
EntrySpeed *
EntrySpeed) - (LimitingSpeed * LimitingSpeed)) / 3.6 / 3.6 / 2 / CumulativeLength;
4825 if(!BuffersOrContinuationNowFlag)
4827 CurrentTrackVectorPosition = NextTrackVectorPosition;
4828 EntryPos = NextEntryPos;
4829 CurrentElementHalfLength = NextElementHalfLength;
4832 ContinuationNextFlag =
true;
4836 while(((CumulativeLength -
FrontElementLength) < DistanceAtHalfBraking) && ((!BuffersOrContinuationNowFlag && !ContinuationNextFlag) ||
4856 if(ExitSpeedHalfSquared < 10)
4866 if(ExitSpeedFullSquared < 10)
4929 double DeltaExitTimeToMaxInSecs;
4930 double DistanceToMax;
4939 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4941 DistanceToMax = EntryHalfLength;
4944 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4945 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4962 double DeltaExitTimeToMaxInSecs;
4963 double DistanceToMax;
4972 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4974 DistanceToMax = EntryHalfLength / 2;
4977 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4978 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4989 if(ExitSpeedHalfSquared < 10)
4999 if(ExitSpeedFullSquared < 10)
5018 if((EntryPos == 0) || (EntryPos == 2))
5040 if(NextTrackVectorPosition > -1)
5042 int NextElementLength;
5043 if(NextEntryPos > 1)
5051 double NextStoppingSpeed = sqrt(3.6 * 3.6 * 2 *
BrakeRate * NextElementLength);
5247 int ElementCount = 0;
5255 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition;
5313 if((EntryPos == 0) || (EntryPos == 2))
5335 CurrentTrackVectorPosition = NextTrackVectorPosition;
5336 EntryPos = NextEntryPos;
5338 if(ElementCount > 1000)
5366 throw Exception(
"Error - failed to set ReturnVal in ClearToNextSignal()");
5391 bool PlatformFoundFlag =
false, StopRequired =
false, SkipRouteCheck =
false, RouteOrPartRouteSet =
false;
5392 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition, ElementNumber = 0, Distance = 0;
5393 int RouteStartPosition;
5395 int PlatformPosition;
5397 int EntryPos =
LeadEntryPos, ExitPos, NextEntryPos, RouteID;
5413 if(Distance > (4000 + LeadElementDistance))
5436 if(OtherTrain.
LeadElement == CurrentTrackVectorPosition)
5439 if((OtherCommand ==
"Fjo") || (OtherCommand ==
"jbo") || (OtherCommand ==
"cdt") || (OtherCommand ==
"Frh") ||
5485 if(!PlatformFoundFlag)
5487 PlatformPosition = CurrentTrackVectorPosition;
5490 PlatformFoundFlag =
true;
5506 if((EntryPos == 0) || (EntryPos == 2))
5550 if(ElementNumber < 2)
5552 SkipRouteCheck =
true;
5556 SkipRouteCheck =
false;
5558 if(ElementNumber == 1)
5560 RouteStartPosition = CurrentTrackVectorPosition;
5570 if(ElementNumber > 1)
5574 RouteOrPartRouteSet =
true;
5578 RouteOrPartRouteSet =
false;
5581 if(!SkipRouteCheck && !RouteOrPartRouteSet)
5588 int ExitLink = CurrentTrackElement.
Link[ExitPos];
5589 if((ExitLink == 1) || (ExitLink == 3) || (ExitLink == 7) || (ExitLink == 9))
5601 Distance += CurrentTrackElement.
Length01;
5605 Distance += CurrentTrackElement.
Length23;
5607 NextTrackVectorPosition = CurrentTrackElement.
Conn[ExitPos];
5608 NextEntryPos = CurrentTrackElement.
ConnLinkPos[ExitPos];
5609 CurrentTrackVectorPosition = NextTrackVectorPosition;
5610 EntryPos = NextEntryPos;
5647 return(RepeatHeadCode);
5669 bool FrontValid =
false, RearValid =
false;
5670 TTrackElement FrontAdjacentTrackElement, RearAdjacentTrackElement;
5674 TrainToBeJoinedBy = NULL;
5688 int TrainToBeJoinedByID = -1;
5709 if((TrainToBeJoinedByID < 0) && RearValid)
5728 if(TrainToBeJoinedByID < 0)
5730 TrainToBeJoinedBy = NULL;
5735 if(!TrainToBeJoinedBy->
Stopped())
5737 TrainToBeJoinedBy = NULL;
5747 void TTrain::LogAction(
int Caller, AnsiString OwnHeadCode, AnsiString OtherHeadCode,
TActionType ActionType, AnsiString LocationName, AnsiString SplitDistribution,
5748 TDateTime TimetableNonRepeatTime,
bool Warning)
5785 AnsiString(ActionType) +
"," + LocationName +
"," +
HeadCode);
5786 AnsiString BaseLog =
"", WarningBaseLog =
"", ReminderBaseLog =
"", PerfLog =
"", ActionLog =
"";
5787 int IntMinsLate = 0;
5788 bool TTEvent =
false;
5793 ActionLog =
" arrived at ";
5803 ActionLog =
" terminated at ";
5809 ActionLog =
" departed from ";
5812 if(ActionType ==
Pass)
5814 ActionLog =
" passed ";
5819 ActionLog =
" created at ";
5821 if(ActionType ==
Enter)
5823 ActionLog =
" entered railway at ";
5827 ActionLog =
" changed its description to '" +
Description +
"' at ";
5835 if(ActionType ==
Leave)
5837 ActionLog =
" left railway at ";
5842 ActionLog =
" split mass%-Power% = " + SplitDistribution +
" from front to ";
5847 ActionLog =
" split mass%-Power% = " + SplitDistribution +
" from rear to ";
5852 ActionLog =
" joined by ";
5857 ActionLog =
" changed direction at ";
5862 ActionLog =
" became new service ";
5867 ActionLog =
" taken under signaller control at ";
5871 ActionLog =
" restored to timetable control at ";
5877 ActionLog =
" REMOVED FROM RAILWAY DUE TO CRASH at ";
5881 ActionLog =
" REMOVED FROM RAILWAY DUE TO DERAILMENT at ";
5885 ActionLog =
" REMOVED FROM RAILWAY at ";
5890 ActionLog =
" received signaller authority to proceed";
5894 ActionLog =
" received signaller authority to step forward";
5898 ActionLog =
" changed direction under signaller control at ";
5902 ActionLog =
" received signaller authority to pass stop signal";
5906 ActionLog =
" received signaller instruction to stop";
5910 ActionLog =
" stopped on signaller instruction ";
5914 ActionLog =
" joined under signaller control by ";
5918 ActionLog =
" suffered an onboard power failure at ";
5922 ActionLog =
" failure repaired at ";
5926 ActionLog =
" left railway under signaller control at ";
5928 if(OtherHeadCode !=
"")
5930 OtherHeadCode +=
" at ";
5962 bool TimePerformance =
true;
5970 TimePerformance =
false;
5974 double MinsLate = ((double)(ActualTime -
GetTrainTime(1, TimetableNonRepeatTime))) * 1440;
5976 if(ActionType ==
Pass)
5990 IntMinsLate = int(ceil(MinsLate));
5994 IntMinsLate = int(floor(MinsLate));
5996 if(IntMinsLate == 0)
5998 PerfLog =
" on time";
6000 else if(IntMinsLate == 1)
6002 PerfLog =
" 1 minute late";
6004 else if(IntMinsLate == -1)
6006 PerfLog =
" 1 minute early";
6008 else if(IntMinsLate > 1)
6010 PerfLog =
" " + AnsiString(IntMinsLate) +
" minutes late";
6012 else if(IntMinsLate < -1)
6014 int PosIntMinsLate = -IntMinsLate;
6015 PerfLog =
" " + AnsiString(PosIntMinsLate) +
" minutes early";
6017 if(LocationName.Pos(
'-') > 0)
6019 PerfLog =
"," + PerfLog;
6032 if(ReminderBaseLog !=
"")
6035 ReminderBaseLog =
"";
6039 if((ActionType ==
Arrive) && (IntMinsLate == 0))
6043 else if((ActionType ==
Arrive) && (IntMinsLate > 0))
6048 else if((ActionType ==
Arrive) && (IntMinsLate < 0))
6054 else if((ActionType ==
Pass) && (IntMinsLate == 0))
6058 else if((ActionType ==
Pass) && (IntMinsLate > 0))
6063 else if((ActionType ==
Pass) && (IntMinsLate < 0))
6069 else if((ActionType ==
Leave) && (IntMinsLate == 0))
6073 else if((ActionType ==
Leave) && (IntMinsLate > 0))
6078 else if((ActionType ==
Leave) && (IntMinsLate < 0))
6084 else if((ActionType ==
Depart) && (IntMinsLate == 0))
6088 else if((ActionType ==
Depart) && (IntMinsLate > 0))
6107 AnsiString LocName =
"";
6178 if(LocationName ==
"")
6182 int RearTrainRearPos, RearTrainFrontPos, RearTrainExitPos;
6183 int FrontTrainRearPos, FrontTrainFrontPos;
6186 if(LocationName ==
"")
6188 throw Exception(
"Error - LocationName not set in FrontTrainSplit");
6192 bool TemporaryDelay =
false;
6194 MidEntryPos, FrontTrainFrontPos, FrontTrainRearPos, RearTrainFrontPos, RearTrainRearPos, TemporaryDelay))
6218 AnsiString SplittingTrainDescription =
Description;
6225 for(
int x = 0; x < 4; x++)
6245 double NewTrainPowerAtRail;
6251 NewTrainMass =
Mass * double(MassPercent)/100.0;
6253 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
6254 if(NewTrainPowerAtRail == 0)
6256 NewTrainPowerAtRail = 0.08;
6264 NewTrainMass =
Mass;
6292 if(!SplitTrainExplicitDescription)
6337 if(LocationName ==
"")
6341 int RearTrainRearPos, RearTrainFrontPos;
6342 int FrontTrainRearPos, FrontTrainFrontPos, FrontTrainExitPos;
6345 if(LocationName ==
"")
6347 throw Exception(
"Error - LocationName not set in RearTrainSplit");
6351 bool TemporaryDelay =
false;
6353 MidEntryPos, FrontTrainFrontPos, FrontTrainRearPos, RearTrainFrontPos, RearTrainRearPos, TemporaryDelay))
6377 AnsiString SplittingTrainDescription =
Description;
6384 for(
int x = 0; x < 4; x++)
6404 double NewTrainPowerAtRail;
6410 NewTrainMass =
Mass * double(MassPercent)/100.0;
6412 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
6413 if(NewTrainPowerAtRail == 0)
6415 NewTrainPowerAtRail = 0.08;
6423 NewTrainMass =
Mass;
6451 if(!SplitTrainExplicitDescription)
6542 TTrain *TrainToBeJoinedBy;
6575 double OtherBrakeForce = TrainToBeJoinedBy->
MaxBrakeRate * TrainToBeJoinedBy->
Mass;
6577 double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->
Mass +
Mass);
6641 int RouteNumber = -1;
6646 int CorrectRouteID = OR.
RouteID;
6652 bool FirstPass =
true;
6657 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6791 for(
int x = 0; x < IncNum; x++)
6824 else if(Ptr->
Command ==
"jbo")
6829 else if(Ptr->
Command ==
"dsc")
6834 else if(Ptr->
Command ==
"cms")
6845 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6851 bool IncludeFER =
false;
6859 if(!IncludeFER && (Ptr->
Command ==
"Fer"))
6864 else if(IncludeFER && (Ptr->
Command ==
"Fer"))
6875 else if(Ptr->
Command ==
"Fjo")
6881 else if(Ptr->
Command ==
"Frh")
6891 else if(Ptr->
Command ==
"Frh-sh")
6942 else if(Ptr->
Command ==
"jbo")
6947 else if(Ptr->
Command ==
"dsc")
6952 else if(Ptr->
Command ==
"cms")
6957 else if(Ptr->
Command ==
"cdt")
6965 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
7387 int RouteNumber = -1;
7392 int CorrectRouteID = OR.
RouteID;
7398 bool FirstPass =
true;
7403 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
7431 ",FloatingLabelNextString" +
"," +
HeadCode);
7432 AnsiString RetStr =
"", LocationName =
"";
7435 if(ActionTime == TDateTime(-1))
7439 if(ActionTime == TDateTime(-1))
7445 if(ActionTime != TDateTime(-1))
7453 throw Exception(
"Error - start entry in FloatingLabelNextString");
7497 else if(Ptr->
Command ==
"Fns")
7503 else if(Ptr->
Command ==
"F-nshs")
7534 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7536 else if(Ptr->
Command ==
"Frh")
7538 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7540 else if(Ptr->
Command ==
"Fer")
7542 AnsiString AllowedExits =
"";
7545 else if(Ptr->
Command ==
"Fjo")
7550 else if(Ptr->
Command ==
"jbo")
7555 else if(Ptr->
Command ==
"fsp")
7560 else if(Ptr->
Command ==
"rsp")
7565 else if(Ptr->
Command ==
"cdt")
7569 else if(Ptr->
Command ==
"dsc")
7573 else if(Ptr->
Command ==
"cms")
7582 throw Exception(
"Error - start entry in FloatingLabelNextString where TTClockTime > ActionTime");
7626 else if(Ptr->
Command ==
"Fns")
7632 else if(Ptr->
Command ==
"F-nshs")
7663 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7665 else if(Ptr->
Command ==
"Frh")
7667 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7669 else if(Ptr->
Command ==
"Fer")
7671 AnsiString AllowedExits =
"";
7674 else if(Ptr->
Command ==
"Fjo")
7679 else if(Ptr->
Command ==
"jbo")
7684 else if(Ptr->
Command ==
"fsp")
7689 else if(Ptr->
Command ==
"rsp")
7694 else if(Ptr->
Command ==
"cdt")
7698 else if(Ptr->
Command ==
"dsc")
7702 else if(Ptr->
Command ==
"cms")
7711 throw Exception(
"Error - start entry in FloatingLabelNextString in final 'else'");
7755 else if(Ptr->
Command ==
"Fns")
7761 else if(Ptr->
Command ==
"F-nshs")
7792 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7794 else if(Ptr->
Command ==
"Frh")
7796 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7798 else if(Ptr->
Command ==
"Fer")
7800 AnsiString AllowedExits =
"";
7803 else if(Ptr->
Command ==
"Fjo")
7808 else if(Ptr->
Command ==
"jbo")
7813 else if(Ptr->
Command ==
"fsp")
7818 else if(Ptr->
Command ==
"rsp")
7823 else if(Ptr->
Command ==
"cdt")
7827 else if(Ptr->
Command ==
"dsc")
7831 else if(Ptr->
Command ==
"cms")
7975 + AnsiString(RptNum) +
",GetNewServiceDepartureInfo," +
HeadCode);
7976 AnsiString DepTime =
"", EventTime =
"";
7977 bool CDTFlag =
false;
7979 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
7980 AnsiString TowardsLocation =
"";
7983 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
7985 TowardsLocation = AVI->LocationName;
7987 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
7996 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
8003 if(AVI->Command ==
"cdt")
8008 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
8023 RetStr +=
"\nNew service splits at approx. " + EventTime;
8027 if(AVI->Command ==
"jbo")
8046 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
8061 RetStr +=
"\nNew service finishes and forms another new service at approx. " + EventTime;
8065 if(AVI->Command ==
"Fjo")
8084 if(AVI->Command ==
"Frh")
8086 RetStr +=
"\nNew service finishes and remains at the location.";
8090 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
8097 if(TowardsLocation !=
"")
8099 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
8103 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
8108 if(TowardsLocation !=
"")
8110 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
8114 RetStr +=
"\nNew service departs at " + DepTime;
8123 if(TowardsLocation !=
"")
8125 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
8129 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
8134 if(TowardsLocation !=
"")
8136 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
8140 RetStr +=
"\nNew service departs at approx. " + DepTime;
8157 if(TowardsLocation !=
"")
8159 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
8163 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
8168 if(TowardsLocation !=
"")
8170 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
8174 RetStr +=
"\nNew service departs at approx. " + DepTime;
8193 ",FloatingTimetableString" +
"," +
HeadCode);
8194 AnsiString RetStr =
"", PartStr =
"";
8196 bool SkipDep =
false, SkipDepActedOn =
false;
8202 throw Exception(
"Error - start entry in FloatingTimetableString");
8205 bool FirstPass =
true;
8212 AnsiString TrainLoc =
"";
8265 AnsiString TrainLoc =
"";
8306 else if(Ptr->
Command ==
"Fns")
8312 else if(Ptr->
Command ==
"F-nshs")
8345 else if(Ptr->
Command ==
"Frh")
8349 else if(Ptr->
Command ==
"Fer")
8351 AnsiString AllowedExits =
"";
8354 else if(Ptr->
Command ==
"Fjo")
8359 else if(Ptr->
Command ==
"jbo")
8364 else if(Ptr->
Command ==
"fsp")
8374 PartStr+=
", split mass%-Power% = 50-50";
8377 else if(Ptr->
Command ==
"rsp")
8387 PartStr+=
", split mass%-Power% = 50-50";
8390 else if(Ptr->
Command ==
"cdt")
8394 else if(Ptr->
Command ==
"dsc")
8398 else if(Ptr->
Command ==
"cms")
8404 RetStr = RetStr +
'\n' + PartStr;
8418 SkipDepActedOn =
true;
8429 RetStr =
"Timetable finished";
8433 RetStr =
"No timetable";
8437 return(
"Timetable:\n" + RetStr);
8590 bool ForwardHeadCode;
8594 ForwardHeadCode =
true;
8599 ForwardHeadCode =
false;
8742 if(ColourNumber == 0)
8746 else if(ColourNumber == 1)
8750 else if(ColourNumber == 2)
8754 else if(ColourNumber == 3)
8758 else if(ColourNumber == 4)
8762 else if(ColourNumber == 5)
8766 else if(ColourNumber == 6)
8770 else if(ColourNumber == 7)
8774 else if(ColourNumber == 8)
8778 else if(ColourNumber == 9)
8782 else if(ColourNumber == 10)
8786 else if(ColourNumber == 11)
8790 else if(ColourNumber == 12)
8794 else if(ColourNumber == 13)
8798 else if(ColourNumber == 14)
8810 for(
int x = 0; x < 4; x++)
8817 for(
int x = 0; x < 4; x++)
8902 if((LocationAndMarker[1] !=
'*') && (LocationAndMarker.Length() > 6))
8905 AnsiString Location = LocationAndMarker.SubString(1, LocationAndMarker.Length() - 6);
8906 bool GiveMessagesFalse =
false;
8907 bool CheckLocationsExistInRailwayTrue =
true;
8914 AnsiString Marker = LocationAndMarker.SubString(LocationAndMarker.Length() - 5, 6);
8917 if(Marker[6] ==
'1')
9382 bool HideFlashingTrain =
true;
9385 Graphics::TBitmap *SmallTrainBitmap;
9426 HideFlashingTrain =
false;
9431 HideFlashingTrain =
false;
9436 HideFlashingTrain =
false;
9441 HideFlashingTrain =
false;
9446 HideFlashingTrain =
false;
9450 if((
LeadElement > -1) && (!HideFlashingTrain || Flash))
9454 if((
MidElement > -1) && (!HideFlashingTrain || Flash))
9478 for(
int y = 0; y < 3; y++)
9482 bool FoundFlag =
false;
9493 if(IMPair.first != IMPair.second)
9520 if((LocationName ==
"") && (
MidElement > -1))
9524 if((LocationName ==
"") && (
LagElement > -1))
9528 if(LocationName ==
"")
9530 throw Exception(
"Error - Location name not set in TrainAtLocation");
9541 for(
int x = 0; x < 4; x++)
9554 for(
int x = 0; x < 4; x++)
9575 AnsiString(LinkNumber) +
"," +
HeadCode);
9627 int DistanceToRedSignal = 0, DistanceToExit = -1;
9628 float TimeToAct = 0, LastTimeToExit =
TimeToExit;
9632 float MinsEarly = 0;
9633 TDateTime DepartureTime;
9634 TDateTime ArrivalTime;
9662 if(TempTTE < LastTimeToExit)
9697 if(TempTTE < LastTimeToExit)
9720 if(TempTTE < LastTimeToExit)
9750 if(TempTTE < LastTimeToExit)
9773 if(TempTTE < LastTimeToExit)
9816 float CurrentStopTime;
9817 float LaterStopTime;
9818 float RecoverableTime;
9826 if((DistanceToRedSignal == -1) && (DistanceToExit == -1))
9833 bool DistanceToRedSignalSet = (DistanceToRedSignal > -1);
9834 bool DistanceToExitSet = (DistanceToExit > -1);
9835 int GenericDistance = DistanceToRedSignal;
9836 if(DistanceToExitSet)
9838 GenericDistance = DistanceToExit;
9854 float TimeToSubtract, TotalStopTime;
9857 TimeToSubtract = RecoverableTime;
9900 if(CurrentStopTime > 0)
9902 TotalStopTime = CurrentStopTime + LaterStopTime;
9911 else if((MinsEarly > 0) && !
Stopped())
9913 TotalStopTime = LaterStopTime + MinsEarly;
9917 if(LaterStopTime == 0)
9919 TotalStopTime = CurrentStopTime;
9925 TotalStopTime = CurrentStopTime + LaterStopTime - TimeToSubtract;
9928 if(AvTrackSpeed < 30)
9932 int Speed = AvTrackSpeed;
9942 if(DistanceToRedSignalSet)
9944 TimeToAct = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9954 TimeToExit = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9983 if((NextEntryPos == 0) || (NextEntryPos == 2))
10141 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10180 if(AVEntry0.
Command ==
"Snt")
10184 int IncrementalMinutes = 0;
10185 int IncrementalDigits = 0;
10193 throw Exception(
"Error - Repeat entry && less than two trains for Snt entry: " + TDEntry.
HeadCode);
10229 if(AVEntry0.
Command ==
"Snt-sh")
10234 int IncrementalMinutes = 0;
10235 int IncrementalDigits = 0;
10243 throw Exception(
"Error - Repeat entry && less than two trains for Snt-sh entry: " + TDEntry.
HeadCode);
10287 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10367 AnsiString Loc =
"";
10368 bool ElementFound =
false;
10373 ElementFound =
true;
10378 ElementFound =
true;
10383 ElementFound =
true;
10412 else if(AVEntryPtr->
Command ==
"Fer")
10414 bool CorrectExit =
false;
10421 CorrectExit =
true;
10526 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10544 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10559 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10570 bool TTrainController::AddTrain(
int Caller,
int RearPosition,
int FrontPosition, AnsiString HeadCode,
int StartSpeed,
int Mass,
double MaxRunningSpeed,
10571 double MaxBrakeRate,
double PowerAtRail, AnsiString ModeStr,
TTrainDataEntry *TrainDataEntryPtr,
int RepeatNumber,
int IncrementalMinutes,
10572 int IncrementalDigits,
int SignallerSpeed,
bool SignallerControl,
TActionEventType &EventType)
10574 LogEvent(AnsiString(Caller) +
",AddTrain," + AnsiString(RearPosition) +
"," + AnsiString(FrontPosition) +
"," + HeadCode +
"," + AnsiString(StartSpeed) +
10575 "," + AnsiString(Mass) +
"," + ModeStr);
10577 "," + HeadCode +
"," + AnsiString(StartSpeed) +
"," + AnsiString(Mass) +
"," + ModeStr);
10579 int RearExitPos = -1;
10581 for(
int x = 0; x < 4; x++)
10588 if(RearExitPos == -1)
10590 throw Exception(
"Error, RearExit == -1 in AddTrain");
10592 bool ReportFlag =
true;
10597 ReportFlag =
false;
10609 if(ModeStr ==
"Timetable")
10615 if(MaxRunningSpeed < 10)
10617 MaxRunningSpeed = 10;
10619 if(SignallerSpeed < 10)
10621 SignallerSpeed = 10;
10623 TTrain *NewTrain =
new TTrain(0, RearPosition, RearExitPos, HeadCode, StartSpeed, Mass, MaxRunningSpeed, MaxBrakeRate, PowerAtRail, TrainMode,
10624 TrainDataEntryPtr, RepeatNumber, IncrementalMinutes, IncrementalDigits, SignallerSpeed);
10631 if(SignallerControl)
10661 if(!SignallerControl)
10676 if(!SignallerControl)
10687 AnsiString Loc =
"";
10704 if(!SignallerControl)
10723 int RouteNumber = -1;
10724 bool SignalsSet =
false;
10731 int RouteStartPosition;
10735 if(FirstPair.first == RouteNumber)
10737 RouteStartPosition = FirstPair.second;
10739 else if(SecondPair.first == RouteNumber)
10741 RouteStartPosition = SecondPair.second;
10745 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 1st of 2 calls to SetAllRearwardsSignals in AddTrain");
10751 else if(RouteNumber > -1)
10771 int LinkedRouteNumber = -1;
10792 int RouteStartPosition;
10796 if(FirstPair.first == RouteNumber)
10798 RouteStartPosition = FirstPair.second;
10800 else if(SecondPair.first == RouteNumber)
10802 RouteStartPosition = SecondPair.second;
10806 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 2nd of 2 calls to SetAllRearwardsSignals in AddTrain");
10812 else if(RouteNumber > -1)
10832 int LinkedRouteNumber = -1;
10853 AnsiString(TrackVectorNumber));
10856 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10865 throw Exception(
"Error, VecPos not set in EntryPos");
10867 if(
TrainVectorAt(2, VecPos).LeadElement == TrackVectorNumber)
10872 else if(
TrainVectorAt(4, VecPos).MidElement == TrackVectorNumber)
10877 else if(
TrainVectorAt(6, VecPos).LagElement == TrackVectorNumber)
10891 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10899 throw Exception(
"Error - No Train identified in TrainVectorAtIdent with ID = " + AnsiString(TrainID));
10909 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10930 return(RepeatTime);
10939 AnsiString RetStr =
"", PartStr =
"";
10947 if((Ptr->Command !=
"") && (Ptr->Command[1] ==
'S'))
10955 if(Ptr->SignallerControl)
10957 RetStr =
"Train under signaller control";
10962 if(Ptr->ArrivalTime == Ptr->DepartureTime)
10973 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime != TDateTime(-1)))
10977 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime == TDateTime(-1)))
10981 else if(Ptr->FormatType ==
PassTime)
10985 else if(Ptr->Command ==
"Fns")
10991 else if(Ptr->Command ==
"F-nshs")
10994 Ptr->NonRepeatingShuttleLinkHeadCode +
" at " + Ptr->LocationName;
11001 else if((Ptr->Command ==
"Fns-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
11008 else if((Ptr->Command ==
"Fns-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
11011 Ptr->NonRepeatingShuttleLinkHeadCode, +
" at " + Ptr->LocationName;
11014 else if((Ptr->Command ==
"Frh-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
11021 else if((Ptr->Command ==
"Frh-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
11023 PartStr =
"Terminate at " + Ptr->LocationName;
11025 else if(Ptr->Command ==
"Frh")
11027 PartStr =
"Terminate at " + Ptr->LocationName;
11029 else if(Ptr->Command ==
"Fer")
11031 AnsiString AllowedExits;
11035 else if(Ptr->Command ==
"Fjo")
11038 Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
11040 else if(Ptr->Command ==
"jbo")
11043 (50, Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
11045 else if(Ptr->Command ==
"fsp")
11050 else if(Ptr->Command ==
"rsp")
11055 else if(Ptr->Command ==
"cdt")
11059 else if(Ptr->Command ==
"dsc")
11063 else if(Ptr->Command ==
"cms")
11069 RetStr = RetStr +
'\n' + PartStr;
11077 while(Ptr < TTDEPtr->ActionVector.end() && (Count < 33) && ((Ptr->Command ==
"") || ((Ptr->Command !=
"") && (Ptr->Command[1] !=
'F'))));
11088 TTrainDataEntry *LinkedTrainDataPtr,
int IncrementalMinutes,
int IncrementalDigits, AnsiString RetStr)
11091 + AnsiString(RptNum) +
",ControllerGetNewServiceDepartureInfo," + TDEPtr->
HeadCode);
11092 AnsiString DepTime =
"", EventTime =
"";
11093 bool CDTFlag =
false;
11095 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
11096 AnsiString TowardsLocation =
"";
11099 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
11101 TowardsLocation = AVI->LocationName;
11103 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
11112 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
11118 if(AVI->Command ==
"cdt")
11120 CDTFlag = !CDTFlag;
11123 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
11126 RetStr +=
"\nNew service splits at " + EventTime;
11130 if(AVI->Command ==
"jbo")
11133 RetStr +=
"\nNew service joined by " +
GetRepeatHeadCode(70, AVI->OtherHeadCode, RptNum, IncrementalDigits) +
" at " + EventTime;
11137 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
11140 RetStr +=
"\nNew service finishes and forms another new service at " + EventTime;
11144 if(AVI->Command ==
"Fjo")
11147 RetStr +=
"\nNew service finishes and joins " +
TrainController->
GetRepeatHeadCode(71, AVI->OtherHeadCode, RptNum, IncrementalDigits) +
" at " + EventTime;
11151 if(AVI->Command ==
"Frh")
11153 RetStr +=
"\nNew service finishes and remains at location.";
11157 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
11162 if(TowardsLocation !=
"")
11164 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
11168 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
11173 if(TowardsLocation !=
"")
11175 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
11179 RetStr +=
"\nNew service departs at " + DepTime;
11348 ActiveTrackElementNameMapEntry.second = 0;
11354 std::ifstream TTBLFile(FileName, std::ios_base::binary);
11357 if(TTBLFile.is_open())
11359 char *TrainTimetableString =
new char[10000];
11361 bool EndOfFile =
false;
11364 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
11366 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
11373 delete[] TrainTimetableString;
11377 AnsiString OneLine(TrainTimetableString);
11378 bool FinalCallFalse =
false;
11379 while((Count == 0) && !
ProcessOneTimetableLine(5, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
11383 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
11384 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
11389 TimetableMessage(GiveMessages,
"Timetable invalid - unable to find a valid start time on its own line");
11391 delete[] TrainTimetableString;
11395 OneLine = AnsiString(TrainTimetableString);
11401 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
11403 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
11413 OneLine = AnsiString(TrainTimetableString);
11415 if(OneLine.Length() > 9999)
11417 TimetableMessage(GiveMessages,
"Timetable contains a line that is too long - 10,000 or more characters!");
11419 delete[] TrainTimetableString;
11423 bool FinalCallFalse =
false;
11424 if(!
ProcessOneTimetableLine(6, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
11428 delete[] TrainTimetableString;
11432 if(EndOfFile && (Count < 2))
11435 TimetableMessage(GiveMessages,
"Timetable has too few or no relevant entries - must have a start time on its own line and at least one train");
11437 delete[] TrainTimetableString;
11443 delete[] TrainTimetableString;
11448 TimetableMessage(GiveMessages,
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
11459 bool CheckLocationsExistInRailway)
11589 AnsiString((
short)FinalCall) +
"," + AnsiString((
short)CheckLocationsExistInRailway));
11599 if(OneLine[1] !=
'*')
11601 int DelimPos = OneLine.Pos(
';');
11602 int CPos = OneLine.Pos(
',');
11603 if((CPos > 0) && (CPos < DelimPos))
11618 bool AllCommas =
true;
11620 for(
int x = 1; x < OneLine.Length() + 1; x++)
11622 if(OneLine[x] !=
',')
11627 if(AllCommas || (OneLine ==
""))
11642 AnsiString First =
"", Second =
"", Third =
"", Fourth =
"";
11643 int RearStartOrRepeatMins = 0, FrontStartOrRepeatDigits = 0, NumberOfRepeats = 0;
11644 TDateTime EventTime(0), ArrivalTime(0), DepartureTime(0);
11645 TDateTime StartTime(0);
11647 bool Warning =
false;
11674 AnsiString TrainInfoStr =
"", HeadCode =
"", Description =
"";
11675 int StartSpeed = 0, MaxRunningSpeed = 0, Mass = 0;
11676 double MaxBrakeRate = 0;
11677 double PowerAtRail = 0;
11678 int SignallerSpeed = 0;
11679 if(OneLine[1] ==
'*')
11685 int Pos = OneLine.Pos(
',');
11688 int SubStringLength = 20;
11689 if(OneLine.Length() < 20)
11691 SubStringLength = OneLine.Length();
11693 TimetableMessage(GiveMessages,
"Error in timetable - entry incomplete: see '" + OneLine.SubString(1, SubStringLength) +
"'....");
11697 TrainInfoStr = OneLine.SubString(1, Pos - 1);
11698 if(!
SplitTrainInfo(0, TrainInfoStr, HeadCode, Description, StartSpeed, MaxRunningSpeed, Mass, MaxBrakeRate, PowerAtRail, SignallerSpeed,
11709 TempTrainDataEntry.
HeadCode = HeadCode;
11713 if(Description !=
"")
11718 TempTrainDataEntry.
Mass = Mass;
11726 AnsiString NewRemainder = OneLine.SubString(Pos + 1, OneLine.Length() - Pos);
11729 while(NewRemainder[NewRemainder.Length()] ==
',')
11731 if(NewRemainder.Length() > 1)
11733 NewRemainder = NewRemainder.SubString(1, NewRemainder.Length() - 1);
11742 if(NewRemainder ==
"")
11744 TimetableMessage(GiveMessages,
"Error in timetable - no events following train: '" + OneLine +
"'");
11749 int CommaCount = 0;
11750 for(
int x = 1; x < NewRemainder.Length() + 1; x++)
11752 if(NewRemainder[x] ==
',')
11757 if(CommaCount == 0)
11759 if((NewRemainder.SubString(7, 3) !=
"Snt") || (NewRemainder[NewRemainder.Length()] !=
'S'))
11761 int SubStringLength = 20;
11762 if(OneLine.Length() < 20)
11764 SubStringLength = OneLine.Length();
11767 "Error in timetable - must have at least a start and a finish event for a train that is not started under signaller control - see line beginning: '" +
11768 OneLine.SubString(1, SubStringLength) +
"'....");
11773 AnsiString OneEntry =
"";
11778 bool FinishFlag =
false;
11780 for(
int x = 0; x < CommaCount + 1; x++)
11782 if((CommaCount == 0) || (x < CommaCount))
11787 if(CommaCount == 0)
11789 OneEntry = NewRemainder;
11794 Pos = NewRemainder.Pos(
',');
11795 OneEntry = NewRemainder.SubString(1, Pos - 1);
11796 NewRemainder = NewRemainder.SubString(Pos + 1, NewRemainder.Length() - Pos);
11802 RearStartOrRepeatMins = 0;
11803 FrontStartOrRepeatDigits = 0;
11804 NumberOfRepeats = 0;
11805 if(!
SplitEntry(0, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11806 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11808 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
11819 if(Warning && (Second ==
"Frh"))
11821 TimetableMessage(GiveMessages,
"Error in line - '" + OneEntry +
"': warnings cannot be given for 'Frh' events");
11825 if(Warning && (Second ==
"Fjo"))
11828 "': warnings cannot be given for 'Fjo' events, for a train join warning add a 'W' prefix to the 'jbo' event");
11865 TimetableMessage(GiveMessages,
"Error in timetable - First event not a start event: '" + OneEntry +
"'");
11869 if((Second ==
"Snt") && (Fourth ==
'S') && (NewRemainder !=
""))
11871 if(NewRemainder[1] !=
'R')
11874 "Error in timetable - the only event that can follow a train created under signaller control is a repeat, see '" +
11880 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11884 if((HeadCode ==
"") || (Description ==
"") || (MaxRunningSpeed == 0) || (Mass == 0) || (MaxBrakeRate == 0))
11887 TimetableMessage(GiveMessages,
"Error in timetable - train information incomplete before 'Snt' or 'Snt-sh' start event: '" +
11893 if((Second ==
"Sfs") || (Second ==
"Sns") || (Second ==
"Sns-sh") || (Second ==
"Sns-fsh"))
11898 TimetableMessage(GiveMessages,
"Error in timetable - headcode missing before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11903 if((StartSpeed != 0) || (MaxRunningSpeed != 0) || (Mass != 0) || (MaxBrakeRate != 0) || (PowerAtRail != 0))
11906 "Error in timetable - information additional to a headcode & optional description given before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11922 TDateTime TempTime;
11928 ActionVectorEntry.
Warning = Warning;
11944 ActionVectorEntry.
Command = Second;
11959 else if(FormatType ==
TimeCmd)
11965 ActionVectorEntry.
Command = Second;
11973 ActionVectorEntry.
Command = Second;
11974 ActionVectorEntry.
ExitList = ExitList;
11982 ActionVectorEntry.
Command = Second;
11996 ActionVectorEntry.
Command = Second;
12007 ActionVectorEntry.
Command = Second;
12017 ActionVectorEntry.
Command = Second;
12019 if((Second ==
"fsp") || (Second ==
"rsp"))
12034 ActionVectorEntry.
Command = Second;
12043 ActionVectorEntry.
Command = Second;
12049 ActionVectorEntry.
Command = Second;
12057 ActionVectorEntry.
Command = Second;
12066 ActionVectorEntry.
Command = Second;
12069 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
12074 OneEntry = NewRemainder;
12079 RearStartOrRepeatMins = 0;
12080 FrontStartOrRepeatDigits = 0;
12081 NumberOfRepeats = 0;
12082 if((FinishFlag) && (OneEntry[1] !=
'R'))
12085 TimetableMessage(GiveMessages,
"Error in timetable - Last event = '" + OneEntry +
"'. An earlier finish event has been found with something other than a repeat following it - only a repeat can follow a finish event.");
12089 if(OneEntry[1] !=
'R')
12091 if(!
SplitEntry(1, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
12092 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
12094 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'.\nIf the program version is not the latest the "
12095 "timetable may have features that aren't compatible with the version in use.");
12112 TimetableMessage(GiveMessages,
"Error in timetable - last event should be a finish: '" + OneEntry +
"'");
12119 TDateTime TempTime;
12125 ActionVectorEntry.
Warning = Warning;
12132 ActionVectorEntry.
Command = Second;
12140 ActionVectorEntry.
Command = Second;
12149 ActionVectorEntry.
Command = Second;
12158 ActionVectorEntry.
Command = Second;
12168 ActionVectorEntry.
Command = Second;
12169 ActionVectorEntry.
ExitList = ExitList;
12173 ActionVectorEntry.
Command = Second;
12175 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
12180 if(!
SplitRepeat(0, OneEntry, RearStartOrRepeatMins, FrontStartOrRepeatDigits, NumberOfRepeats, GiveMessages))
12196 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
12215 if((HeadCode[HeadCode.Length() - 1] <
'0') || (HeadCode[HeadCode.Length() - 1] >
'9'))
12220 if((HeadCode[HeadCode.Length()] <
'0') || (HeadCode[HeadCode.Length()] >
'9'))
12235 if(TimeStr.Length() < 5)
12240 if((TimeStr[1] <
'0') || (TimeStr[1] >
'9'))
12245 if((TimeStr[2] <
'0') || (TimeStr[2] >
'9'))
12250 if(TimeStr[3] !=
':')
12255 if((TimeStr[4] <
'0') || (TimeStr[4] >
'5'))
12260 if((TimeStr[5] <
'0') || (TimeStr[5] >
'9'))
12265 while(TimeStr.Length() > 5)
12267 TimeStr = TimeStr.SubString(1, TimeStr.Length() - 1);
12269 double WholeHours = (AnsiString(TimeStr[1]) + AnsiString(TimeStr[2])).ToDouble();
12270 double FracHour = ((AnsiString(TimeStr[4]) + AnsiString(TimeStr[5])).ToDouble()) / 60.0;
12272 if((WholeHours + FracHour) >= 95.98334)
12277 Time = TDateTime((WholeHours + FracHour) / 24);
12284 bool TTrainController::SplitEntry(
int Caller, AnsiString OneEntry,
bool GiveMessages,
bool CheckLocationsExistInRailway, AnsiString &First, AnsiString &Second,
12285 AnsiString &Third, AnsiString &Fourth,
int &RearStartOrRepeatMins,
int &FrontStartOrRepeatDigits,
TTimetableFormatType &FormatType,
12294 TDateTime TempTime;
12296 if(OneEntry.Length() > 0)
12298 if(OneEntry[1] ==
'W')
12301 OneEntry = OneEntry.SubString(2, OneEntry.Length() - 1);
12305 if(OneEntry ==
"Frh")
12315 if(OneEntry.Length() < 7)
12320 int Pos = OneEntry.Pos(
';');
12328 First = OneEntry.SubString(1, 5);
12334 AnsiString Remainder = OneEntry.SubString(Pos + 1, OneEntry.Length() - Pos);
12337 if((Remainder.Length() >= 3) && (Remainder[1] >=
'0') && (Remainder[1] <=
'9') && (Remainder[2] >=
'0') && (Remainder[2] <=
'9') && (Remainder[3] ==
':'))
12340 if(Remainder.Length() < 7)
12345 Pos = Remainder.Pos(
';');
12352 Second = Remainder.SubString(1, 5);
12358 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12371 Pos = Remainder.Pos(
';');
12374 Second = Remainder;
12375 if(Second ==
"cdt")
12400 if((Pos != 4) && (Pos != 7) && (Pos != 8))
12406 Second = Remainder.SubString(1, Pos - 1);
12408 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12410 Pos = Remainder.Pos(
';');
12417 Third = Remainder.SubString(1, Pos - 1);
12418 Fourth = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12421 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
12424 int SpacePos = Third.Pos(
' ');
12430 AnsiString RearStartStr = Third.SubString(1, SpacePos - 1);
12431 AnsiString FrontStartStr = Third.SubString(SpacePos + 1, Third.Length() - SpacePos);
12433 if(CheckLocationsExistInRailway)
12443 if(Second ==
"Snt")
12466 if(Second ==
"Sns-sh")
12485 if(Second ==
"F-nshs")
12499 if(Second ==
"Sns-fsh")
12513 if(Second ==
"Fns-sh")
12533 if(Second ==
"pas")
12548 if(Second ==
"Fer")
12555 if(CheckLocationsExistInRailway)
12566 if(Second ==
"dsc")
12568 if(Third.Length() > 60)
12570 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters in '" + Third +
"'");
12574 for(
int x = 1; x < Third.Length() + 1; x++)
12577 if((Third[x] <
' ') && (Third[x] >= 0))
12579 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + Third +
"'");
12591 if(Second ==
"cms")
12599 for(
int x = 1; x < Third.Length() + 1; x++)
12601 if((Third[x] <
'0') || (Third[x] >
'9'))
12603 TimetableMessage(GiveMessages,
"Train maximum speed must be a number in '" + Third +
"'");
12608 int MaxRunningSpeed = Third.ToInt();
12611 TimetableMessage(GiveMessages,
"Train maximum running speed [" + Third +
"km/h] can't be greater than 400km/h");
12615 if(MaxRunningSpeed < 10)
12618 TimetableMessage(GiveMessages,
"Train maximum running speed [" + Third +
"km/h] can't be less than 10km/h.");
12633 if((Second !=
"Fns") && (Second !=
"Fjo") && (Second !=
"jbo") && (Second !=
"fsp") && (Second !=
"rsp") && (Second !=
"Sfs") && (Second !=
"Sns") &&
12634 (Second !=
"Frh-sh"))
12646 if(Second ==
"Frh-sh")
12654 if((Second ==
"Fns") || (Second ==
"Fjo") || (Second ==
"Frh-sh"))
12658 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp"))
12662 if((Second ==
"Sfs") || (Second ==
"Sns"))
12667 if((Fourth !=
"") && ((Second ==
"fsp") || (Second ==
"rsp")))
12684 bool ErrorFlag =
false;
12686 if((SplitDistributionString.Length() > 6 ) || (SplitDistributionString.Length() < 3))
12690 int pos = SplitDistributionString.Pos(
'-');
12697 AnsiString MassStr = SplitDistributionString.SubString(1, pos - 1);
12698 AnsiString PowerStr = SplitDistributionString.SubString(pos + 1, SplitDistributionString.Length() - pos);
12701 int x = MassStr.ToInt();
12702 int y = PowerStr.ToInt();
12703 if((x > 99) || (x < 1) || (y > 100) || (y < 0))
12708 catch(
const Exception &e)
12715 TimetableMessage(GiveMessages,
"Error in split distribution " + SplitDistributionString +
", should be 'AA-BB' where AA is the percentage mass (min 1, max 99) and BB the percentage " +
12716 "power for the new split-off train");
12737 if((LocStr.Length() >= 3) && (LocStr[1] >=
'0') && (LocStr[1] <=
'9') && (LocStr[2] >=
'0') && (LocStr[2] <=
'9') && (LocStr[3] ==
':'))
12742 for(
int x = 1; x < LocStr.Length() + 1; x++)
12744 if(((LocStr[x] <
' ') && (LocStr[x] >= 0)) || (LocStr[x] ==
',') || (LocStr[x] ==
';'))
12758 if(CheckLocationsExistInRailway)
12763 "' appears in the timetable but is not a valid name. To be valid the name must be a stopping location and apply to one or more platforms " +
12764 "(not concourses on their own), or to track at a blue non-station named location. BUT NOTE THAT trains can't stop at continuations so a name " +
12765 "that includes a continuation will not be valid.");
12783 if((HeadCode.Length() < 4) || (HeadCode.Length() > 8))
12786 "', length must be between 4 and 8 characters, and last 4 must be a legitimate headcode. This error can also be caused by omitting a service reference after Sns, Snt-sh, Sns-sh, Fns, Fns-sh or Frh-sh");
12791 for(
int x = 1; x < (HeadCode.Length() + 1); x++)
12793 if((HeadCode[x] <
' ') || (HeadCode[x] >
'~'))
12795 TimetableMessage(GiveMessages,
"Non-printable character in headcode '" + HeadCode +
"'");
12801 for(
int x = 3; x >= 0; x--)
12803 if(((HeadCode[HeadCode.Length() - x] <
'A') || (HeadCode[HeadCode.Length() - x] >
'Z')) && ((HeadCode[HeadCode.Length() - x] <
'a') ||
12804 (HeadCode[HeadCode.Length() - x] >
'z')) && ((HeadCode[HeadCode.Length() - x] <
'0') || (HeadCode[HeadCode.Length() - x] >
'9')))
12806 TimetableMessage(GiveMessages,
"Headcode error in '" + HeadCode +
"', headcode must consist of letters and digits only");
12822 AnsiString CurrentID =
"";
12824 if(IDSet.Length() == 0)
12826 TimetableMessage(GiveMessages,
"Must have at least one exit element ID following 'Fer'");
12830 for(
int x = 1; x <= IDSet.Length(); x++)
12833 if(((C <
'0') || (C >
'9')) && (C !=
' ') && (C !=
'N') && (C !=
'-'))
12835 TimetableMessage(GiveMessages,
"Illegal character in the set of element IDs following 'Fer' in '" + IDSet +
"'");
12857 int Pos = IDSet.Pos(
' ');
12868 CurrentID = IDSet.SubString(1, Pos - 1);
12869 IDSet = IDSet.SubString(Pos + 1, IDSet.Length() - Pos);
12881 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' is not an exit");
12888 if(!ExitList.empty())
12890 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
12892 if(*ELIT == VecPos)
12894 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' duplicates an earlier element");
12901 ExitList.push_back(VecPos);
12911 Pos = IDSet.Pos(
' ');
12918 int &Mass,
double &MaxBrakeRate,
double &PowerAtRail,
int &SignallerSpeed,
bool GiveMessages)
12925 AnsiString Remainder =
"";
12926 int SemiColonCount = 0;
12928 for(
int x = 1; x < TrainInfoStr.Length() + 1; x++)
12930 if(TrainInfoStr[x] ==
';')
12935 if((SemiColonCount != 6) && (SemiColonCount != 7) && (SemiColonCount != 1) && (SemiColonCount != 0))
12937 TimetableMessage(GiveMessages,
"Error in train information in '" + TrainInfoStr +
12938 "'. Should be headcode + optional description for a continuing service;" +
12939 " or headcode, description, start speed, max running speed, mass, brake force, power (and optional signaller max. speed) for a new service");
12943 if(SemiColonCount == 0)
12945 HeadCode = TrainInfoStr;
12954 if(SemiColonCount == 1)
12956 Pos = TrainInfoStr.Pos(
';');
12957 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12958 Description = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12964 if(Description ==
"")
12966 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
12970 if(Description.Length() > 60)
12972 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
12976 for(
int x = 1; x < Description.Length() + 1; x++)
12979 if((Description[x] <
' ') && (Description[x] >= 0))
12981 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
12990 Pos = TrainInfoStr.Pos(
';');
12991 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12992 Remainder = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12998 Pos = Remainder.Pos(
';');
12999 Description = Remainder.SubString(1, Pos - 1);
13000 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13001 if(Description ==
"")
13003 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
13007 if(Description.Length() > 60)
13009 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
13013 for(
int x = 1; x < Description.Length() + 1; x++)
13016 if((Description[x] <
' ') && (Description[x] >= 0))
13018 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
13023 Pos = Remainder.Pos(
';');
13024 AnsiString StartSpeedStr = Remainder.SubString(1, Pos - 1);
13026 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13027 if(StartSpeedStr ==
"")
13029 TimetableMessage(GiveMessages,
"Train starting speed missing in '" + TrainInfoStr +
"'");
13033 for(
int x = 1; x < StartSpeedStr.Length() + 1; x++)
13035 if((StartSpeedStr[x] <
'0') || (StartSpeedStr[x] >
'9'))
13037 TimetableMessage(GiveMessages,
"Train start speed contains invalid characters in '" + TrainInfoStr +
"'");
13042 StartSpeed = StartSpeedStr.ToInt();
13048 TimetableMessage(GiveMessages,
"Train starting speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
13052 Pos = Remainder.Pos(
';');
13053 AnsiString MaxRunningSpeedStr = Remainder.SubString(1, Pos - 1);
13055 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13056 if(MaxRunningSpeedStr ==
"")
13058 TimetableMessage(GiveMessages,
"Train maximum running speed missing in '" + TrainInfoStr +
"'");
13062 for(
int x = 1; x < MaxRunningSpeedStr.Length() + 1; x++)
13064 if((MaxRunningSpeedStr[x] <
'0') || (MaxRunningSpeedStr[x] >
'9'))
13066 TimetableMessage(GiveMessages,
"Train maximum running speed contains invalid characters in '" + TrainInfoStr +
"'");
13071 MaxRunningSpeed = MaxRunningSpeedStr.ToInt();
13074 TimetableMessage(GiveMessages,
"Train maximum running speed [" + MaxRunningSpeedStr +
"km/h] can't be greater than 400km/h");
13078 if(MaxRunningSpeed < 10)
13081 TimetableMessage(GiveMessages,
"Train maximum running speed [" + MaxRunningSpeedStr +
"km/h] can't be less than 10km/h.");
13085 Pos = Remainder.Pos(
';');
13086 AnsiString MassStr = Remainder.SubString(1, Pos - 1);
13088 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13091 TimetableMessage(GiveMessages,
"Train mass missing in '" + TrainInfoStr +
"'");
13095 for(
int x = 1; x < MassStr.Length() + 1; x++)
13097 if((MassStr[x] <
'0') || (MassStr[x] >
'9'))
13099 TimetableMessage(GiveMessages,
"Train mass contains invalid characters in '" + TrainInfoStr +
"'");
13104 Mass = MassStr.ToInt() * 1000;
13110 TimetableMessage(GiveMessages,
"Train mass > 10,000 tonnes in '" + TrainInfoStr +
"'. Setting it to 10,000 tonnes");
13116 TimetableMessage(GiveMessages,
"Train mass zero in '" + TrainInfoStr +
"'");
13120 Pos = Remainder.Pos(
';');
13121 AnsiString MaxBrakeForceStr = Remainder.SubString(1, Pos - 1);
13123 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13124 if(MaxBrakeForceStr ==
"")
13126 TimetableMessage(GiveMessages,
"Train braking force missing in '" + TrainInfoStr +
"'");
13130 for(
int x = 1; x < (MaxBrakeForceStr.Length() + 1); x++)
13132 if((MaxBrakeForceStr[x] !=
'.') && ((MaxBrakeForceStr[x] <
'0') || (MaxBrakeForceStr[x] >
'9')))
13134 TimetableMessage(GiveMessages,
"Train braking force contains invalid characters in '" + TrainInfoStr +
"'");
13139 double MaxBrakeForce = MaxBrakeForceStr.ToDouble() * 1000;
13142 if((MaxBrakeForce / Mass) > 1)
13144 MaxBrakeForce = Mass;
13147 TimetableMessage(GiveMessages,
"Train braking force too high in '" + TrainInfoStr +
"'. Setting it to the same as the train mass");
13151 if((MaxBrakeForce / Mass) < 0.01)
13153 MaxBrakeForce = Mass * 0.01;
13156 TimetableMessage(GiveMessages,
"Train braking force too low in '" + TrainInfoStr +
"'. Setting it to 1% of the train mass");
13161 MaxBrakeRate = MaxBrakeForce / Mass * 9.81;
13163 AnsiString GrossPowerStr =
"", SignallerSpeedStr =
"";
13165 if(SemiColonCount == 6)
13167 GrossPowerStr = Remainder;
13168 SignallerSpeedStr =
"30";
13172 Pos = Remainder.Pos(
';');
13173 GrossPowerStr = Remainder.SubString(1, Pos - 1);
13174 SignallerSpeedStr = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13177 if(GrossPowerStr ==
"")
13179 TimetableMessage(GiveMessages,
"Train power missing in '" + TrainInfoStr +
"'");
13183 for(
int x = 1; x < GrossPowerStr.Length() + 1; x++)
13185 if((GrossPowerStr[x] <
'0') || (GrossPowerStr[x] >
'9'))
13187 TimetableMessage(GiveMessages,
"Train power contains invalid characters in '" + TrainInfoStr +
"'");
13193 double GrossPower = GrossPowerStr.ToInt() * 1000;
13200 TimetableMessage(GiveMessages,
"Train power > 100,000kW in '" + TrainInfoStr +
"'. Setting it to 100,000kW");
13204 else if(GrossPower == 0)
13209 else if((GrossPower > 0) && (GrossPower < 10000))
13212 GrossPower = 10000;
13214 PowerAtRail = GrossPower * 0.8;
13218 if(SignallerSpeedStr ==
"")
13220 TimetableMessage(GiveMessages,
"Signaller speed not set in '" + TrainInfoStr +
"', either set a value or remove the extra semicolon");
13224 for(
int x = 1; x < SignallerSpeedStr.Length() + 1; x++)
13226 if((SignallerSpeedStr[x] <
'0') || (SignallerSpeedStr[x] >
'9'))
13228 TimetableMessage(GiveMessages,
"Signaller speed contains invalid characters in '" + TrainInfoStr +
"'");
13233 SignallerSpeed = SignallerSpeedStr.ToInt();
13239 TimetableMessage(GiveMessages,
"Signaller speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
13243 if(SignallerSpeed < 10)
13246 SignallerSpeed = 10;
13249 TimetableMessage(GiveMessages,
"Signaller speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
13267 if(OneEntry.Length() < 7)
13269 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
13273 int SemiColonCount = 0;
13275 for(
int x = 1; x < OneEntry.Length() + 1; x++)
13277 if(OneEntry[x] ==
';')
13282 if(SemiColonCount != 3)
13284 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
13288 if((OneEntry[1] !=
'R') || (OneEntry[2] !=
';'))
13290 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
13294 AnsiString Remainder = OneEntry.SubString(3, OneEntry.Length() - 2);
13299 Pos = Remainder.Pos(
';');
13300 AnsiString MinutesStr = Remainder.SubString(1, Pos - 1);
13302 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13303 if(MinutesStr ==
"")
13305 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute increment segment missing");
13309 if(MinutesStr.Length() > 3)
13312 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute value too high, maximum value is 999");
13316 for(
int x = 1; x < MinutesStr.Length() + 1; x++)
13318 if((MinutesStr[x] <
'0') || (MinutesStr[x] >
'9'))
13320 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in minute increment segment");
13325 RearStartOrRepeatMins = MinutesStr.ToInt();
13326 if(RearStartOrRepeatMins == 0)
13328 TimetableMessage(GiveMessages,
"Repeat minute increment is zero in: '" + OneEntry +
"' - can't have a zero value");
13332 Pos = Remainder.Pos(
';');
13333 AnsiString DigitsStr = Remainder.SubString(1, Pos - 1);
13335 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13336 if(DigitsStr ==
"")
13338 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - headcode increment segment missing");
13342 for(
int x = 1; x < DigitsStr.Length() + 1; x++)
13344 if((DigitsStr[x] <
'0') || (DigitsStr[x] >
'9'))
13346 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in headcode increment segment");
13351 if(DigitsStr.Length() > 2)
13353 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - maximum number of digits for headcode increment is 2");
13357 FrontStartOrRepeatDigits = DigitsStr.ToInt();
13371 "' - a repeating service with incrementing digits must have digits as its last two headcode characters");
13375 AnsiString NumberStr = Remainder;
13377 if(NumberStr ==
"")
13379 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - number of repeats missing");
13383 if(NumberStr.Length() > 4)
13386 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - repeat value too high, no timetabled event can exceed 95 hours & 59 minutes");
13390 for(
int x = 1; x < NumberStr.Length() + 1; x++)
13392 if((NumberStr[x] <
'0') || (NumberStr[x] >
'9'))
13395 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in number of repeats");
13400 NumberOfRepeats = NumberStr.ToInt();
13401 if(NumberOfRepeats == 0)
13403 TimetableMessage(GiveMessages,
"Number of repeats is zero in: '" + OneEntry +
"' - if no repeats are needed the repeat should be omitted");
13678 SecondPassMessage(GiveMessages,
"Error in timetable - there appear to be no train services in the timetable, it must contain at least one");
13699 TwoLocationFlag =
false;
13705 SecondPassMessage(GiveMessages,
"Error in timetable - the following service has no listed events, there must be at least one: " + TDEntry.
HeadCode);
13719 SecondPassMessage(GiveMessages,
"Error in timetable - service must have a start event and at least one other for: " + TDEntry.
HeadCode);
13735 "Error in timetable - a signaller controlled service can have no more than one item (a repeat) after the start event, see: " +
13747 "Error in timetable - a signaller controlled service cannot have any other than a repeat after the start event, see: " + TDEntry.
HeadCode);
13773 SecondPassMessage(GiveMessages,
"Error in timetable - finish events Fns-sh and Frh-sh not permitted immediately after an Snt entry for: " +
13786 SecondPassMessage(GiveMessages,
"Error in timetable - only 'Frh' or 'Fjo' finish events are permitted immediately after "
13787 "an 'Sns' or 'Sfs' event for: " + TDEntry.
HeadCode +
". The program is unable to determine the "
13788 "location of any other type of finish.");
13794 if((AVEntry0.
Command ==
"Snt-sh") || (AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
13800 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event can't immediately follow an 'Snt-sh', 'Sns-sh' or 'Sns-fsh' "
13801 "event for: " + TDEntry.
HeadCode);
13811 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13816 SecondPassMessage(GiveMessages,
"Error in timetable - a start event is present that is not the first event for: " + TDEntry.
HeadCode);
13826 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13831 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat is present that is not the last item for: " + TDEntry.
HeadCode);
13841 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13852 SecondPassMessage(GiveMessages,
"Error in timetable - the last item must be either a finish event or a repeat for: " + TDEntry.
HeadCode);
13862 SecondPassMessage(GiveMessages,
"Error in timetable - the event immediately before the repeat must be a finish for: " + TDEntry.
HeadCode);
13874 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13881 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event must be either the last or last but one for: " + TDEntry.
HeadCode);
13890 SecondPassMessage(GiveMessages,
"Error in timetable - the only event that can follow a finish event is a repeat for: " + TDEntry.
HeadCode);
13909 if((AVEntry0.
Command ==
"Snt") || (AVEntry0.
Command ==
"Snt-sh"))
13911 AnsiString LocationName =
"";
13925 SecondPassMessage(GiveMessages,
"Error in timetable - stopped 'Snt' or 'Snt-sh' followed by an illegal event for: " +
13926 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
13935 if(AVEntry0.
Command ==
"Snt-sh")
13949 SecondPassMessage(GiveMessages,
"Error in timetable - unlocated 'Snt' not followed by 'Fer', 'pas' or an arrival for: " +
13965 SecondPassMessage(GiveMessages,
"Error in timetable - 'Sfs', 'Sns', 'Sns-sh', 'Snt-fsh' or 'Sns-fsh' followed by an illegal event for: " +
13966 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
13978 bool FoundFlag =
false;
13982 if((AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
13984 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13996 SecondPassMessage(GiveMessages,
"Error in timetable - no location departure following an 'Sns-sh' or 'Sns-fsh' event for: " + TDEntry.
HeadCode);
14009 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14034 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14056 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14078 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14103 bool LocFoundFlag, FnsFoundFlag;
14107 LocFoundFlag =
false;
14108 FnsFoundFlag =
false;
14109 for(
int y =
TrainDataVector.at(x).ActionVector.size() - 1; y >= 0; y--)
14114 FnsFoundFlag =
true;
14123 LocFoundFlag =
true;
14134 SecondPassMessage(GiveMessages,
"Error in timetable - the program can't determine the location of an 'Fns' finish, it must be preceded "
14135 "by an event at the same location that has an identified location name, normally an arrival, see "
14142 if(FnsFoundFlag && !LocFoundFlag)
14144 SecondPassMessage(GiveMessages,
"Error in timetable - the program can't determine the location of an 'Fns' finish, it must be preceded "
14145 "by an event at the same location that has an identified location name, normally an arrival, see "
14159 if(AVEntry0.
Command ==
"Sns")
14171 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient actions follwing an 'Sns' event for: " + TDEntry.
HeadCode);
14179 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' event is followed by an illegal event for: " + TDEntry.
HeadCode +
14180 ". The event isn't valid for a stationary train.");
14188 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' event is followed by an illegal event for: " + TDEntry.
HeadCode);
14195 TDateTime SnsEventTime = AVEntry0.
EventTime;
14198 bool BreakFlag =
false;
14201 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
14206 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SnsServiceRef)
14228 if(AVEntry0.
Command ==
"Sfs")
14230 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14238 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event must be followed by a departure and arrival before another split, see " +
TrainDataVector.at(x).ServiceReference);
14250 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14255 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
14275 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14282 SecondPassMessage(GiveMessages,
"Error in timetable - an 'fsp' or 'rsp' event must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
14297 if(AVEntry0.
Command ==
"Sfs")
14309 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient actions follwing an 'Sfs' event for: " + TDEntry.
HeadCode);
14317 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event is followed by an illegal event for: " + TDEntry.
HeadCode +
14318 ". The event isn't valid for a stationary train.");
14326 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event is followed by an illegal event for: " + TDEntry.
HeadCode);
14333 TDateTime SfsEventTime = AVEntry0.
EventTime;
14335 bool BreakFlag =
false;
14338 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
14343 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SfsServiceRef)
14363 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14368 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
14389 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14396 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"' must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
14401 else if((AVEntry.
Command ==
"Sns") || (AVEntry.
Command ==
"Sfs"))
14404 "Please make sure that the finish event of the service that links to this event is preceded by an "
14405 "event at the same location that has an identified location name, normally an arrival.");
14410 else if(AVEntry.
Command ==
"Snt-sh")
14413 "Please make sure that the service starts with zero speed and is at a named location.");
14418 else if((AVEntry.
Command ==
"Sns-fsh") || (AVEntry.
Command ==
"Sns-sh"))
14421 "Please make sure that the event is followed (not necessarily immediately) by a departure.");
14428 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
14441 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14451 SecondPassMessage(GiveMessages,
"Error in timetable - only a repeat can follow a finish event for: " + TDEntry.
HeadCode);
14458 if(AVEntry.
Command ==
"F-nshs")
14463 SecondPassMessage(GiveMessages,
"Error in timetable - F-nshs (shuttle link) must be the last event for: " + TDEntry.
HeadCode);
14491 SecondPassMessage(GiveMessages,
"Error in timetable - a jbo event is followed by an illegal event for: " + TDEntry.
HeadCode +
14492 ". The event isn't valid for a stationary train.");
14502 SecondPassMessage(GiveMessages,
"Error in timetable - a train split can't be the last event for: " + TDEntry.
HeadCode);
14510 SecondPassMessage(GiveMessages,
"Error in timetable - a train split is followed by an illegal event for: " + TDEntry.
HeadCode +
14511 ". The event isn't valid for a stationary train.");
14529 SecondPassMessage(GiveMessages,
"Error in timetable - a 'cdt' is followed by an illegal event for: " + TDEntry.
HeadCode +
14530 ". The event isn't valid for a stationary train.");
14548 SecondPassMessage(GiveMessages,
"Error in timetable - a 'dsc' is followed by an illegal event for: " + TDEntry.
HeadCode +
14549 ". The event isn't valid for a stationary train.");
14567 SecondPassMessage(GiveMessages,
"Error in timetable - a 'cms' is followed by an illegal event for: " + TDEntry.
HeadCode +
14568 ". The event isn't valid for a stationary train.");
14578 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure can't be the last event for: " + TDEntry.
HeadCode);
14586 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure is followed by an illegal event for: " +
14587 TDEntry.
HeadCode +
". The event isn't valid for a moving train.");
14605 SecondPassMessage(GiveMessages,
"Error in timetable - a pass time is followed by an illegal event for: " + TDEntry.
HeadCode +
14606 ". The event isn't valid for a moving train.");
14628 bool LastEntryIsAnArrival =
false;
14635 LastEntryIsAnArrival =
false;
14636 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14643 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
14645 if(LastEntryIsAnArrival)
14649 LastEntryIsAnArrival =
false;
14655 LastEntryIsAnArrival =
true;
14662 LastEntryIsAnArrival =
true;
14663 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14670 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
14672 if(LastEntryIsAnArrival)
14676 LastEntryIsAnArrival =
false;
14682 LastEntryIsAnArrival =
true;
14692 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14700 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival can't be the last event for: " + TDEntry.
HeadCode);
14708 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival is followed by an illegal event for: " + TDEntry.
HeadCode +
14709 ". The event isn't valid for a stationary train.");
14720 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure can't be the last event for: " + TDEntry.
HeadCode);
14728 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure is followed by an illegal event for: " + TDEntry.
HeadCode +
14729 ". The event isn't valid for a moving train.");
14743 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14750 throw Exception(
"Timetable error, TimeLoc event has EventTime not -1 for " + TDEntry.
HeadCode);
14754 throw Exception(
"Timetable error, TimeLoc event has neither arrival nor departure time set for " + TDEntry.
HeadCode);
14761 throw Exception(
"Timetable error, TimeTimeLoc event has EventTime not -1 for " + TDEntry.
HeadCode);
14765 throw Exception(
"Timetable error, TimeTimeLoc event has either arrival or departure time not set for " + TDEntry.
HeadCode);
14774 throw Exception(
"Timetable error, Cmd or PassTime event has EventTime not set for " + TDEntry.
HeadCode);
14778 throw Exception(
"Timetable error, Cmd or PassTime event has either arrival or departure time set for " + TDEntry.
HeadCode);
14785 throw Exception(
"Timetable error, Repeat event has a time set for " + TDEntry.
HeadCode);
14796 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14811 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has a later arrival than departure time for: " +
14819 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has too early an arrival time for: " +
14834 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
14846 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
14858 SecondPassMessage(GiveMessages,
"Error in timetable - a train event has a time that is set too early for: " + TDEntry.
HeadCode +
14859 ", may be before timetable start time");
14870 AnsiString LastLocationName =
"";
14874 bool LastEntryIsAnArrival =
false;
14879 LastEntryIsAnArrival =
false;
14880 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
14881 if(LastLocationName !=
"")
14883 throw Exception(
"Timetable error, moving Snt event has LocationName set for " + TDEntry.
HeadCode);
14885 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size();
14898 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14910 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14923 TwoLocationFlag =
true;
14928 LastEntryIsAnArrival =
false;
14932 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
14935 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
14940 else if(!LastEntryIsAnArrival && (AVEntry.
LocationName == LastLocationName))
14943 "Error in timetable - a location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode);
14949 LastEntryIsAnArrival = !LastEntryIsAnArrival;
14955 LastEntryIsAnArrival =
true;
14956 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
14957 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14969 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14981 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14994 TwoLocationFlag =
true;
14999 LastEntryIsAnArrival =
false;
15003 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
15006 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
15014 "A location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode +
". Please correct if this is an error.\n\nThis warning will not be shown again.");
15021 LastEntryIsAnArrival = !LastEntryIsAnArrival;
15029 AnsiString LocationNameToBeChecked =
"";
15034 unsigned int y = 0;
15048 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
15049 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
15067 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
15076 TwoLocationFlag =
true;
15087 if(TwoLocationFlag)
15097 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15102 throw Exception(
"Error, non- 'Snt', 'Fer' or Repeat event doesn't have a location name set for " + TDEntry.
HeadCode);
15104 AnsiString LocName =
"";
15110 throw Exception(
"Error, 'Snt' event at a stop location doesn't have a location name set for " + TDEntry.
HeadCode);
15117 throw Exception(
"Error, 'Snt' unlocated event has a location name set for " + TDEntry.
HeadCode);
15140 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15165 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15187 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15209 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15228 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15231 if((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh"))
15246 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15251 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has FormatType unset for: " + TDEntry.
HeadCode);
15255 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has SequenceType unset for: " + TDEntry.
HeadCode);
15259 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has LocationType unset for: " + TDEntry.
HeadCode);
15263 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has ShuttleLinkType unset for: " + TDEntry.
HeadCode);
15302 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15304 AnsiString LocName =
TrainDataVector.at(x).ActionVector.at(y).LocationName;
15310 SecondPassMessage(GiveMessages,
"Error in timetable - continuation names (" + LocName +
") must not be included, see service " + HC);
15323 int IncMinutes = 0;
15333 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15339 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat time exceeds 95h 59m, see service " + HC);
15345 if((
double)
TrainDataVector.at(x).ActionVector.at(y).ArrivalTime > -1)
15350 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat event time exceeds 95h 59m, see service " + HC);
15356 if((
double)
TrainDataVector.at(x).ActionVector.at(y).DepartureTime > -1)
15361 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat event time exceeds 95h 59m, see service " + HC);
15374 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15408 if(HeadCode.Length() > 4)
15410 HeadCode = HeadCode.SubString(HeadCode.Length() - 3, 4);
15421 int ForwardCount = 0;
15422 int ReverseCount = 0;
15424 if(MainHeadCode == SecondHeadCode)
15426 SecondPassMessage(GiveMessages,
"Error in timetable - Service " + MainHeadCode +
" has an event that references itself");
15435 if(TDEntry.
HeadCode == MainHeadCode)
15437 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15452 if(ForwardCount == 0)
15455 throw Exception(
"Error, ForwardCount == 0 in CheckForDuplicateCrossReferences after called with found values");
15457 if(ForwardCount > 2)
15460 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + SecondHeadCode +
" from a train whose headcode is " +
15461 MainHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
15470 if(TDEntry.
HeadCode == SecondHeadCode)
15472 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15487 if(ReverseCount == 0)
15489 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + SecondHeadCode);
15494 if(ReverseCount > 2)
15497 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + MainHeadCode +
" from a train whose headcode is " +
15498 SecondHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
15503 if(ForwardCount != ReverseCount)
15505 SecondPassMessage(GiveMessages,
"Error in timetable - " + MainHeadCode +
" has a different number of references to " + SecondHeadCode +
15506 " than the other way round");
15537 int ForwardCount = 0;
15538 int ReverseCount = 0;
15539 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
15548 if(TDEntry.
HeadCode == MainHeadCode)
15550 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15553 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
15558 ForwardEntryPtr = &AVEntry;
15560 ForwardTDVectorNumber = x;
15563 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") ||
15564 (AVEntry.
Command ==
"Frh-sh")))
15569 ForwardEntryPtr = &AVEntry;
15571 ForwardTDVectorNumber = x;
15577 if(ForwardCount == 0)
15580 throw Exception(
"Error, ForwardCount == 0 in CheckCrossReferencesAndSetData after called with found values");
15582 if(ForwardCount > 1)
15584 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + OtherHeadCode +
" from a train whose headcode is " +
15594 if(TDEntry.
HeadCode == OtherHeadCode)
15596 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15599 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
15605 ReverseEntryPtr = &AVEntry;
15606 ReverseTDVectorNumber = x;
15609 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"Frh-sh")))
15615 ReverseEntryPtr = &AVEntry;
15616 ReverseTDVectorNumber = x;
15623 if(ReverseCount == 0)
15625 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + OtherHeadCode);
15630 if(ReverseCount > 1)
15632 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
15639 bool ForwardShuttleStart = ((ForwardEntryPtr->Command ==
"Sns-sh") || (ForwardEntryPtr->Command ==
"Snt-sh"));
15640 bool ForwardShuttleFinish = ((ForwardEntryPtr->Command ==
"Fns-sh") || (ForwardEntryPtr->Command ==
"Frh-sh"));
15641 bool ReverseShuttleStart = ((ReverseEntryPtr->
Command ==
"Sns-sh") || (ReverseEntryPtr->
Command ==
"Snt-sh"));
15642 bool ReverseShuttleFinish = ((ReverseEntryPtr->
Command ==
"Fns-sh") || (ReverseEntryPtr->
Command ==
"Frh-sh"));
15646 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat");
15653 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + OtherHeadCode +
" does not have a repeat");
15658 if(SetDataAndCheckLocations)
15660 if(ForwardEntryPtr->LocationName ==
"")
15662 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
15663 ". One or other service does not have a location set");
15670 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
15671 ". One or other service does not have a location set");
15676 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
15678 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
15679 " is at a different location to the referencing train " + MainHeadCode);
15688 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
15690 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
15691 " has a different event time to the referencing train " + MainHeadCode);
15699 if(ForwardShuttleStart && ReverseShuttleFinish)
15704 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle service " + MainHeadCode +
15705 " first repeat restart time not consistent with finish service " + OtherHeadCode);
15711 if((ReverseEntryPtr->
Command ==
"Sfs") || (ReverseEntryPtr->
Command ==
"Sns"))
15714 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15716 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' or 'Sns' event (" + OtherHeadCode +
15717 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15723 if(ReverseEntryPtr->
Command ==
"Fjo")
15726 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15728 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fjo' event (" + OtherHeadCode +
15729 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15735 if(ReverseEntryPtr->
Command ==
"Fns")
15738 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15740 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' event (" + OtherHeadCode +
15741 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15747 if(ForwardEntryPtr->Command ==
"Sfs")
15749 if((ReverseEntryPtr->
Command !=
"fsp") && (ReverseEntryPtr->
Command !=
"rsp"))
15752 "Error in timetable - unable to find a corresponding split train event for the train that starts from a split whose headcode is " +
15759 if((ForwardEntryPtr->Command ==
"fsp") || (ForwardEntryPtr->Command ==
"rsp"))
15761 if(ReverseEntryPtr->
Command !=
"Sfs")
15763 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sfs' event for the train split whose headcode is " +
15771 if(SetDataAndCheckLocations)
15775 SecondPassMessage(GiveMessages,
"Error in timetable - can't find timetabled location '" + ForwardEntryPtr->LocationName +
"' in railway - perhaps there are concourses without platforms?");
15782 SecondPassMessage(GiveMessages,
"Error in timetable - can't find any named location elements at '" + ForwardEntryPtr->LocationName +
"' - perhaps there are concourses without platforms?");
15788 bool StationLocation =
false;
15791 if(TEIt->LocationName == ForwardEntryPtr->LocationName)
15795 StationLocation =
true;
15799 if(StationLocation)
15803 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
15813 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
15819 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15831 if(ForwardEntryPtr->Command ==
"Sns")
15833 if(ReverseEntryPtr->
Command !=
"Fns")
15835 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fns' event for the 'Sns' train whose headcode is " +
15836 MainHeadCode +
" and is formed from a service with headcode " + OtherHeadCode);
15842 if(ForwardEntryPtr->Command ==
"Fns")
15844 if(ReverseEntryPtr->
Command !=
"Sns")
15846 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns' event for the train whose headcode is " + MainHeadCode +
15847 " and forms a new service with headcode " + OtherHeadCode);
15854 if(SetDataAndCheckLocations)
15856 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15868 if(ForwardEntryPtr->Command ==
"jbo")
15870 if(ReverseEntryPtr->
Command !=
"Fjo")
15872 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fjo' event for the train whose headcode is " + MainHeadCode +
15873 " and is joined by a train with headcode " + OtherHeadCode);
15879 if(ForwardEntryPtr->Command ==
"Fjo")
15881 if(ReverseEntryPtr->
Command !=
"jbo")
15883 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'jbo' event for the train whose headcode is " + MainHeadCode +
15884 " and joins a train with headcode " + OtherHeadCode);
15891 if(SetDataAndCheckLocations)
15893 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15909 if(ForwardShuttleStart)
15912 if(!ReverseShuttleFinish)
15915 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + MainHeadCode +
15916 " from train whose headcode is " + OtherHeadCode +
", has to be Fns-sh, Frh-sh");
15922 if(ReverseShuttleStart)
15925 if(!ForwardShuttleFinish)
15928 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + OtherHeadCode +
15929 " from train whose headcode is " + MainHeadCode +
", has to be Fns-sh, Frh-sh");
15936 if(SetDataAndCheckLocations)
15938 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15951 bool MainRepeat =
false, OtherRepeat =
false;
15961 OtherRepeat =
true;
15964 if((MainRepeat && !OtherRepeat) || (!MainRepeat && OtherRepeat))
15966 SecondPassMessage(GiveMessages,
"Error in timetable - only one repeat is provided for the train whose headcode is " + MainHeadCode +
15967 " and the associated train with headcode " + OtherHeadCode);
15972 if(MainRepeat && OtherRepeat)
15978 SecondPassMessage(GiveMessages,
"Error in timetable - repeat items don't correspond for the train whose headcode is " + MainHeadCode +
15979 " and the associated train with headcode " + OtherHeadCode);
16001 while(Input[1] ==
' ')
16003 if(Input.Length() > 1)
16005 Input = Input.SubString(2, Input.Length() - 1);
16019 while(Input[Input.Length()] ==
' ')
16021 if(Input.Length() > 1)
16023 Input = Input.SubString(1, Input.Length() - 1);
16033 AnsiString Output =
"";
16034 bool DelimiterFound =
false;
16036 for(
int x = 1; x < Input.Length() + 1; x++)
16040 if(Input[x] ==
' ')
16045 if((Input[x] !=
',') && (Input[x] !=
';'))
16047 DelimiterFound =
false;
16048 Output = Output + Input[x];
16052 DelimiterFound =
true;
16053 Output = Output + Input[x];
16065 DelimiterFound =
false;
16066 for(
int x = Input.Length(); x > 0; x--)
16070 if(Input[x] ==
' ')
16075 if((Input[x] !=
',') && (Input[x] !=
';'))
16077 DelimiterFound =
false;
16078 Output = AnsiString(Input[x]) + Output;
16082 DelimiterFound =
true;
16083 Output = AnsiString(Input[x]) + Output;
16108 if((AVEntry0.
Command !=
"Snt") && (AVEntry0.
Command !=
"Snt-sh"))
16110 throw Exception(
"Error, first event not 'Snt' or 'Snt-sh' in IsSNTEntryLocated");
16122 LocationName = LocRear;
16126 LocationName = LocFront;
16128 if(LocationName ==
"")
16149 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
16190 int RearPosition = 0, FrontPosition = 0;
16193 if(RearPosition < 0)
16200 if(FrontPosition < 0)
16212 for(
int x = 0; x < 4; x++)
16214 if(RearTrackElement.
Conn[x] == FrontPosition)
16229 TimetableMessage(GiveMessages,
"Front of train attempting to start on a continuation at: " + FrontElementStr);
16236 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + FrontElementStr);
16242 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + RearElementStr);
16273 AnsiString(RearExitPos));
16284 int FrontPosition = RearTrackElement.
Conn[RearExitPos];
16286 int FrontEntryPos = RearTrackElement.
ConnLinkPos[RearExitPos];
16289 AnsiString RearName, FrontName;
16305 FrontName = FrontTrackElement.
ElementID;
16308 int LockedVectorNumber;
16428 if(((RearTrackElement.
Attribute == 1) && (RearExitPos == 1)) || ((RearTrackElement.
Attribute == 0) && (RearExitPos == 3)))
16433 StopTTClockMessage(157, HeadCode +
" can't be created, points set wrongly at " + RearName);
16441 if(((FrontTrackElement.
Attribute == 1) && (FrontEntryPos == 1)) || ((FrontTrackElement.
Attribute == 0) && (FrontEntryPos == 3)))
16446 StopTTClockMessage(158, HeadCode +
" can't be created, points set wrongly at " + RearName);
16480 "," + AnsiString(IncDigits));
16483 throw Exception(
"Error, last 2 characters not both digits and IncDigits > 0 in GetRepeatHeadCode");
16488 return(BaseHeadCode);
16490 int BaseDigits = BaseHeadCode.SubString(3, 2).ToInt();
16491 int NextRepeatDigits = BaseDigits + (IncDigits * RepeatNumber);
16493 while(NextRepeatDigits >= 100)
16495 NextRepeatDigits -= 100;
16497 AnsiString NextRepeatDigitsStr = AnsiString(NextRepeatDigits);
16499 if(NextRepeatDigitsStr.Length() < 2)
16501 NextRepeatDigitsStr = AnsiString(
'0') + NextRepeatDigitsStr;
16503 AnsiString NextRepeatHeadCode = BaseHeadCode.SubString(1, 2) + NextRepeatDigitsStr;
16506 return(NextRepeatHeadCode);
16514 AnsiString(RepeatNumber) +
"," + AnsiString(IncMinutes));
16515 TDateTime NextRepeatTime = BasicTime + TDateTime(((
double)(RepeatNumber * IncMinutes)) / 1440.0);
16517 return(NextRepeatTime);
16526 AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes));
16527 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
16528 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
16529 int RepeatSecs = RepeatMinutes * 60;
16531 if((ForwardSecs > (ReverseSecs - RepeatSecs + 10)) || (ForwardSecs < (ReverseSecs - RepeatSecs - 10)))
16565 NonRepeatingHeadCode);
16566 int ForwardCount = 0;
16567 int ReverseCount = 0;
16568 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
16578 if(TDEntry.
HeadCode == MainHeadCode)
16580 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16586 ForwardEntryPtr = &AVEntry;
16588 ForwardTDVectorNumber = x;
16593 if(ForwardCount == 0)
16596 throw Exception(
"Error, ForwardCount == 0 in CheckNonRepeatingShuttleLinksAndSetData after called with found values");
16598 if(ForwardCount > 1)
16600 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + NonRepeatingHeadCode +
" from a train whose headcode is " +
16610 if(TDEntry.
HeadCode == NonRepeatingHeadCode)
16612 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16619 ReverseEntryPtr = &AVEntry;
16620 ReverseTDVectorNumber = x;
16626 if(ReverseCount == 0)
16628 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + NonRepeatingHeadCode);
16633 if(ReverseCount > 1)
16635 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
16636 NonRepeatingHeadCode);
16641 if(((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh")) && (MainTrainDataPtr->
ActionVector.back().FormatType ==
Repeat))
16643 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle connecting train " + MainHeadCode +
" shouldn't have a repeat");
16648 if((ForwardEntryPtr->Command !=
"F-nshs") && (ForwardEntryPtr->Command !=
"Sns-fsh") && (MainTrainDataPtr->
ActionVector.back().FormatType !=
Repeat))
16650 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat item");
16655 if(SetDataAndCheckLocations)
16657 if(ForwardEntryPtr->LocationName ==
"")
16659 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
16660 ". One or other service does not have a location set");
16667 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
16668 ". One or other service does not have a location set");
16673 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
16675 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + NonRepeatingHeadCode +
16676 " is at a different location to the referencing train " + MainHeadCode);
16682 if(ForwardEntryPtr->Command ==
"F-nshs")
16685 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
16687 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle in-link service " + MainHeadCode +
16688 " finish time not consistent with start time of shuttle service " + NonRepeatingHeadCode);
16694 if(ForwardEntryPtr->Command ==
"Fns-sh")
16698 MainTrainDataPtr->
ActionVector.back().RearStartOrRepeatMins, MainTrainDataPtr->
ActionVector.back().NumberOfRepeats))
16700 SecondPassMessage(GiveMessages,
"Error in timetable - service " + NonRepeatingHeadCode +
", which links out from shuttle service " + MainHeadCode +
16701 ", has the wrong start time. It should correspond to the finish time of the last shuttle.");
16707 if((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh"))
16710 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
16712 SecondPassMessage(GiveMessages,
"Error in timetable - the non repeating link service " + NonRepeatingHeadCode +
16713 " appears in the same sequence as the corresponding shuttle service " + MainHeadCode);
16731 if(ForwardEntryPtr->Command ==
"Sns-sh")
16733 if(ReverseEntryPtr->
Command !=
"F-nshs")
16735 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'F-nshs' event for the 'Sns-sh' train whose headcode is " +
16736 MainHeadCode +
" and is a new shuttle service formed from the service with headcode " + NonRepeatingHeadCode);
16742 if(ForwardEntryPtr->Command ==
"F-nshs")
16744 if(ReverseEntryPtr->
Command !=
"Sns-sh")
16746 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns-sh' event for the 'F-nshs' train whose headcode is " +
16747 MainHeadCode +
" and forms a new shuttle service with headcode " + NonRepeatingHeadCode);
16754 if(SetDataAndCheckLocations)
16756 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
16768 if(ForwardEntryPtr->Command ==
"Sns-fsh")
16770 if(ReverseEntryPtr->
Command !=
"Fns-sh")
16773 "Error in timetable - unable to find a corresponding 'Fns-sh' event for the 'Sns-fsh' non-shuttle service whose headcode is " + MainHeadCode +
16774 " formed from a shuttle service with headcode " + NonRepeatingHeadCode);
16780 if(ForwardEntryPtr->Command ==
"Fns-sh")
16782 if(ReverseEntryPtr->
Command !=
"Sns-fsh")
16785 "Error in timetable - unable to find a corresponding 'Sns-fsh' event for the 'Fns-sh' shuttle service whose headcode is " + MainHeadCode +
16786 " and forms a new non-shuttle service with headcode " + NonRepeatingHeadCode);
16793 if(SetDataAndCheckLocations)
16795 ForwardEntryPtr->NonRepeatingShuttleLinkEntryPtr = OtherTrainDataPtr;
16819 +
"," + AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes) +
"," + AnsiString(RepeatNumber));
16820 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
16821 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
16822 int RepeatSecs = RepeatMinutes * RepeatNumber * 60;
16824 if((ReverseSecs > (ForwardSecs + RepeatSecs + 10)) || (ReverseSecs < (ForwardSecs + RepeatSecs - 10)))
16848 throw Exception(
"Error - last entry in " + TDEntryPtr->
HeadCode +
" service is not a repeat - should have already found this error");
16851 AnsiString OriginalHeadCode = TDEntryPtr->
HeadCode;
16852 AnsiString LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
16854 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
16856 SecondPassMessage(GiveMessages,
"Error in timetable - last event in shuttle service " + TDEntryPtr->
HeadCode +
" is not 'Fns', 'Fns-sh' or 'Frh-sh'");
16861 while(LastActionCommand ==
"Fns")
16863 TDEntryPtr = (TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr;
16864 LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
16865 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
16868 "Error in timetable - last event in a continuation shuttle service (i.e links back to a shuttle) whose headcode is " + TDEntryPtr->
HeadCode +
16869 " is not 'Fns', 'Fns-sh' or 'Frh-sh'");
16876 if((TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr != ShuttleStartAddress)
16879 " is a shuttle finish, but it doesn't link back to the start of the original shuttle starting service " + OriginalHeadCode +
16880 ". The linking of two or more shuttles is not permitted.");
16900 ShowMessage(
ServiceReference +
" (not a valid service ref.): " + Message);
16918 ShowMessage(Message);
16927 int Mins = Input, Hrs = 0;
16933 AnsiString AnsiMins = AnsiString(Mins);
16934 if(AnsiMins.Length() == 1)
16936 AnsiMins =
"0" + AnsiMins;
16938 AnsiString AnsiHrs = AnsiString(Hrs);
16939 if(AnsiHrs.Length() == 1)
16941 AnsiHrs =
"0" + AnsiHrs;
16944 return(AnsiHrs +
':' + AnsiMins);
16988 AnsiString(ActionEventType) +
"," + LocationID);
16989 AnsiString BaseLog =
"", Prefix =
"", ErrorLog =
"", WarningStr =
"";
16994 Prefix =
" ERROR: ";
16997 Prefix =
" HELD: ";
16998 ErrorLog =
" can't enter railway, train obstructing entry position ";
16999 WarningStr =
" can't enter railway, train obstructing entry position ";
17004 Prefix =
" HELD: ";
17005 ErrorLog =
" can't enter railway, route set against it at entry position ";
17006 WarningStr =
" can't enter railway, route set against it at entry position ";
17011 Prefix =
" HELD: ";
17012 ErrorLog =
" can't be created, train obstructing at ";
17013 WarningStr =
" can't be created, train obstructing at ";
17018 Prefix =
" HELD: ";
17019 ErrorLog =
" can't be created on a locked route at ";
17020 WarningStr =
" can't be created on a locked route at ";
17025 Prefix =
" HELD: ";
17026 ErrorLog =
" can't enter on a locked route at ";
17027 WarningStr =
" can't enter on a locked route at ";
17032 Prefix =
" HELD: ";
17033 ErrorLog =
" can't be created, points set wrongly at ";
17034 WarningStr =
" can't be created, points set wrongly at ";
17039 ErrorLog =
" left railway unexpectedly at ";
17044 ErrorLog =
" left railway at an incorrect exit at ";
17049 ErrorLog =
" failed to split - location too short at ";
17050 WarningStr =
" failed to split, location too short at ";
17055 Prefix =
" HELD: ";
17056 ErrorLog =
" unable to split - other train obstructing at ";
17057 WarningStr =
" unable to split - other train obstructing at ";
17062 ErrorLog =
" stopped at buffers unexpectedly at position ";
17066 ErrorLog =
" failed to stop at ";
17071 ErrorLog =
" failed to split at ";
17076 ErrorLog =
" failed to be joined by other train at ";
17081 ErrorLog =
" failed to change its description at ";
17086 ErrorLog =
" failed to change its maximum speed at ";
17091 ErrorLog =
" failed to join other train at ";
17096 ErrorLog =
" failed to terminate at ";
17101 ErrorLog =
" failed to form new service at ";
17106 ErrorLog =
" failed to exit railway ";
17111 ErrorLog =
" failed to change direction at ";
17116 ErrorLog =
" failed to pass ";
17121 ErrorLog =
" facing buffers and unable to start at ";
17125 ErrorLog =
" DERAILED at position ";
17126 Prefix =
" DERAILMENT: ";
17131 ErrorLog =
" CRASHED INTO BUFFERS at ";
17132 Prefix =
" CRASH: ";
17137 ErrorLog =
" CRASHED INTO ROAD TRAFFIC AT A LEVEL CROSSING at ";
17138 Prefix =
" CRASH: ";
17143 ErrorLog =
" CRASHED INTO " + OtherHeadCode +
" at position ";
17144 Prefix =
" CRASH: ";
17148 else if(ActionEventType ==
FailSPAD)
17150 ErrorLog =
" PASSED SIGNAL AT DANGER at position ";
17151 Prefix =
" SPAD: ";
17156 ErrorLog =
"Signals reset ahead of train, route cancelled at position ";
17157 Prefix =
" SPAD RISK: ";
17162 ErrorLog =
" forced a route cancellation by occupying it incorrectly at ";
17166 Prefix =
" WARNING: ";
17167 ErrorLog =
" waiting to join " + OtherHeadCode +
" at ";
17168 WarningStr =
" waiting to join " + OtherHeadCode +
" at ";
17173 Prefix =
" WARNING: ";
17174 ErrorLog =
" waiting to be joined by " + OtherHeadCode +
" at ";
17175 WarningStr =
" waiting to be joined by " + OtherHeadCode +
" at ";
17180 Prefix =
" WARNING: ";
17181 ErrorLog =
" is without power so it can't depart from ";
17182 WarningStr =
" is without power so it can't depart from ";
17187 Prefix =
" WARNING: ";
17188 ErrorLog =
" can't depart because there is a train in front at ";
17189 WarningStr =
" can't depart because there is a train in front at ";
17227 std::ofstream OutFile(
"TrainData.csv");
17231 ShowMessage(
"Output file TrainData.csv failed to open");
17238 OutFile <<
"HeadCode" <<
',' <<
"Description" <<
',' <<
"StartSpeed" <<
',' <<
"MaxRunningSpeed" <<
',' <<
"NumberOfTrains" <<
'\n' <<
'\n';
17243 OutFile <<
',' <<
"FormatType" <<
',' <<
"EventTime" <<
',' <<
"ArrivalTime" <<
',' <<
"DepartureTime" <<
',' <<
"LocationName" <<
',' <<
"Command" <<
17244 ',' <<
"OtherHeadCode" <<
',' <<
"LinkedTrainEntryPtr" <<
',' <<
"RearStartOrRepeatMins" <<
',' <<
"FrontStartOrRepeatDigits" <<
',' <<
17245 "RepeatNumber" <<
'\n' <<
'\n';
17246 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
17249 AnsiString TimetableEntryTypeStr;
17255 TimetableEntryTypeStr =
"NoFormat";
17261 TimetableEntryTypeStr =
"TimeLoc";
17267 TimetableEntryTypeStr =
"TimeTimeLoc";
17273 TimetableEntryTypeStr =
"TimeCmd";
17279 TimetableEntryTypeStr =
"StartNew";
17285 TimetableEntryTypeStr =
"TimeCmdHeadCode";
17291 TimetableEntryTypeStr =
"FinRemHere";
17297 TimetableEntryTypeStr =
"FNSShuttle";
17303 TimetableEntryTypeStr =
"SNTShuttle";
17309 TimetableEntryTypeStr =
"SNSShuttle";
17315 TimetableEntryTypeStr =
"SNSNonRepeatFromShuttle";
17321 TimetableEntryTypeStr =
"FSHNewService";
17327 TimetableEntryTypeStr =
"Repeat";
17333 TimetableEntryTypeStr =
"Default";
17344 OutFile <<
',' <<
',' <<
"Mass" <<
',' <<
"MaxBrakeRate" <<
',' <<
"PowerAtRail" <<
',' <<
"TrainID" <<
',' <<
"RunningEntry" <<
'\n' <<
'\n';
17345 for(
unsigned int y = 0; y <
TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
17348 AnsiString RunningEntryStr;
17354 RunningEntryStr =
"NotStarted";
17360 RunningEntryStr =
"Running";
17366 RunningEntryStr =
"Exited";
17370 OutFile <<
',' <<
',' << TOD.
TrainID <<
',' << RunningEntryStr.c_str() <<
',' <<
'\n';
17387 ShowMessage(Message);
17388 BaseTime = TDateTime::CurrentDateTime();
17402 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
17415 TTrain *NewTrain =
new TTrain(1, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
17417 for(
int x = 0; x < NumberOfTrains; x++)
17419 *NewTrain =
TTrain(2, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
17439 int NumberOfTrains;
17446 for(
int x = 0; x < NumberOfTrains; x++)
17483 for(
int x = 0; x < LockedRouteVectorSize; x++)
17490 LockedRouteObject.
LockStartTime = TDateTime(LockStartTimeDouble);
17501 int LockedRouteVectorSize;
17508 for(
int x = 0; x < LockedRouteVectorSize; x++)
17566 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
17574 ContinuationAutoSigObject.
PassoutTime = TDateTime(PassoutTimeDouble);
17585 int ContinuationAutoSigVectorSize;
17592 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
17662 if(AVFirstEntry.
Command ==
"Snt")
17686 CTEMMP.second = CTEEntry;
17693 throw Exception(
"Error, Last ActionVectorEntry not a repeat in BuildContinuationTrainExpectationMultiMap");
17701 CTEMMP.second = CTEEntry;
17722 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
17739 if((VecPos < 0) || (VecPos >= (
int)
TrainVector.size()))
17741 throw Exception(
"Out of Range Error, vector size: " + AnsiString(
TrainVector.size()) +
", VecPos: " + AnsiString(VecPos) +
" in TrainVectorAt");
17752 AnsiString RetStr =
"", PartStr =
"";
17867 AnsiString TTFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17871 TTFileName = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
17873 AnsiString ShortTTName =
"";
17875 for(
int x = TTFileName.Length(); x > 0; x--)
17877 if(TTFileName[x] ==
'\\')
17879 ShortTTName = TTFileName.SubString(x + 1, TTFileName.Length() - x - 4);
17884 ShowMessage(
"Creates two timetables named " + ShortTTName +
17885 " in the 'Formatted timetables' folder, one in service order in '.csv' format, and one in chronological order in '.txt' format");
17887 Screen->Cursor = TCursor(-11);
17889 AnsiString FormatNoDPStr =
"#######0";
17890 AnsiString TableTitle =
"", TimetableTimeStr =
"", MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"", FirstHeadCode =
"", Header =
"";
17893 TableTitle =
"Railway: " + RailwayTitle +
"; Timetable: " + TimetableTitle +
"; Start time: " + TimetableTimeStr;
17900 MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"";
17902 if(TrainDataEntry.
Mass > 0)
17904 MassStr =
"; Mass " + AnsiString::FormatFloat(FormatNoDPStr, ((
double)TrainDataEntry.
Mass) / 1000) +
"Te; ";
17908 PowerStr =
"Power " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
PowerAtRail / 1000 / 0.8) +
"kW; ";
17912 BrakeStr =
"Brake force " + AnsiString::FormatFloat(FormatNoDPStr, (TrainDataEntry.
MaxBrakeRate * TrainDataEntry.
Mass / 9810)) +
"Te; ";
17916 MaxSpeedStr =
"Maximum speed " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
MaxRunningSpeed) +
" km/h";
17918 FirstHeadCode = TrainDataEntry.
HeadCode;
17919 int IncDigits = 0, IncMinutes = 0;
17921 if(!ActionVector.empty())
17923 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
17925 IncDigits = ActionVector.at(ActionVector.size() - 1).FrontStartOrRepeatDigits;
17926 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
17944 for(
unsigned int z = 0; z < ActionVector.size(); z++)
17949 AnsiString PartStr =
"", TimeStr =
"";
17966 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
17970 PartStr =
"Created at " + ActionVectorEntry.
LocationName;
17980 PartStr =
"Enters at " + LocName;
17993 PartStr =
"Created at " + LocName;
18007 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
18012 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
18018 else if(ActionVectorEntry.
Command ==
"Sfs")
18020 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" split from";
18024 else if(ActionVectorEntry.
Command ==
"Sns")
18026 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
18034 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
18040 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
18048 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
18051 AnsiString FirstHeadCode = TDE->
HeadCode;
18055 TimeStr =
GetRepeatHeadCode(36, FirstHeadCode, LastRepeatNumber, IncrementalDigits) +
" at " +
18067 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
18069 OneTTEntry.
Action = PartStr;
18070 OneTTEntry.
Time = TimeStr;
18072 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
18077 PartStr =
"Arrives & departs " + ActionVectorEntry.
LocationName;
18083 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
18088 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
18096 else if(ActionVectorEntry.
Command ==
"jbo")
18098 PartStr =
"Joined at " + ActionVectorEntry.
LocationName +
" by";
18102 else if(ActionVectorEntry.
Command ==
"fsp")
18106 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
18110 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
18115 else if(ActionVectorEntry.
Command ==
"rsp")
18119 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
18123 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
18128 else if(ActionVectorEntry.
Command ==
"cdt")
18130 PartStr =
"Changes direction at " + ActionVectorEntry.
LocationName;
18133 else if(ActionVectorEntry.
Command ==
"dsc")
18135 PartStr =
"Changes description at " + ActionVectorEntry.
LocationName;
18138 else if(ActionVectorEntry.
Command ==
"cms")
18140 PartStr =
"Change maximum speed to " + ActionVectorEntry.
NewMaxSpeed +
" at " + ActionVectorEntry.
LocationName;
18146 if(ActionVectorEntry.
Command ==
"Fns")
18148 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
18152 else if(ActionVectorEntry.
Command ==
"F-nshs")
18154 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
18160 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service ";
18167 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
18173 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
18180 PartStr =
"Terminates shuttle service at " + ActionVectorEntry.
LocationName;
18185 else if(ActionVectorEntry.
Command ==
"Frh")
18187 PartStr =
"Terminates at " + ActionVectorEntry.
LocationName;
18192 if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
18196 else if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
18206 else if(ActionVectorEntry.
Command ==
"Fer")
18208 AnsiString AllowedExits;
18212 else if(ActionVectorEntry.
Command ==
"Fjo")
18214 PartStr =
"At " + ActionVectorEntry.
LocationName +
" joins";
18223 OneTTEntry.
Action = PartStr;
18224 OneTTEntry.
Time = TimeStr;
18231 AllTTTrains->push_back(OneTTLine);
18235 std::ofstream TTFile(TTFileName.c_str());
18239 StopTTClockMessage(64,
"Formatted timetable file failed to open - can't be created");
18240 delete AllTTTrains;
18275 TTFile << TableTitle.c_str() <<
'\n' <<
'\n';
18276 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
18278 TTFile << AllTTTrains->at(x).Header.c_str();
18281 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
18283 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
18285 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str() <<
',';
18289 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str();
18292 TTFile <<
'\n' <<
'\n';
18294 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.size(); z++)
18296 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.at(z).Action.c_str() <<
',';
18297 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
18299 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
18301 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str() <<
',';
18305 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str();
18310 TTFile <<
'\n' <<
'\n';
18315 AnsiString TTFileName2 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
18317 TTFileName2 = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName2 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".txt";
18319 std::ofstream TTFile2(TTFileName2.c_str());
18323 StopTTClockMessage(67,
"Chronological timetable file failed to open - can't be created");
18324 delete AllTTTrains;
18328 typedef std::multimap<AnsiString, AnsiString>TAnsiMultiMap;
18329 std::multimap<AnsiString, AnsiString>::iterator AMMIT;
18330 std::pair<AnsiString, AnsiString>AnsiMultiMapEntry;
18332 TAnsiMultiMap *TAMM =
new TAnsiMultiMap;
18337 TTFile2 << TableTitle.c_str() <<
'\n' <<
'\n';
18338 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
18340 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
18342 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.size(); z++)
18344 bool GiveMessagesFalse =
false;
18345 AnsiString TimeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time;
18346 AnsiString HeadCodeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode;
18347 AnsiString ActionString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Action;
18352 AnsiString OtherHeadCode = TimeString.SubString(1, 4);
18353 TimeString = TimeString.SubString(9, 5);
18354 ActionString +=
" " + OtherHeadCode;
18356 if(TimeString.SubString(1, 7) ==
"End at ")
18359 TimeString = TimeString.SubString(8, 5);
18361 AnsiString OneLine = TimeString +
' ' + HeadCodeString +
' ' + ActionString +
'\n';
18362 AnsiMultiMapEntry.first = TimeString;
18363 AnsiMultiMapEntry.second = OneLine;
18364 TAMM->insert(AnsiMultiMapEntry);
18369 for(AMMIT = TAMM->begin(); AMMIT != TAMM->end(); AMMIT++)
18371 TTFile2 << (AMMIT->second).c_str();
18373 delete AllTTTrains;
18382 bool AtLocChecked,
bool DirChecked,
int ArrRange,
int DepRange)
18386 bool AnalysisError =
false;
18387 AnsiString SequenceLog =
"SequenceLog\n";
18430 TTrainDataVector::iterator TDVIt, TDVCopyIt;
18432 int IteratorNumber = 0;
18433 AnsiString AnsiSuffix =
"";
18440 if(TDVCopyIt->HeadCode == TDVIt->HeadCode)
18443 AnsiSuffix = AnsiString(Suffix);
18444 TDVCopyIt->ServiceReference = TDVIt->HeadCode +
"/" + AnsiSuffix;
18445 TDVCopyIt->HeadCode = TDVIt->HeadCode +
"/" + AnsiSuffix;
18451 int Increment = 0, SlashPos;
18453 AnsiString LinkedHeadCode;
18457 for(AVEIt = TDVCopyIt->ActionVector.begin(); AVEIt != TDVCopyIt->ActionVector.end(); AVEIt++)
18459 if(AVEIt->LinkedTrainEntryPtr != NULL)
18468 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
18470 if(LinkedHeadCode[x] ==
'/')
18472 SlashPos = LinkedHeadCode.Length() - x + 1;
18475 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
18476 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
18477 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
18483 AVEIt->OtherHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
18487 AVEIt->OtherHeadCode =
"";
18489 if(AVEIt->NonRepeatingShuttleLinkEntryPtr != NULL)
18491 Increment = AVEIt->NonRepeatingShuttleLinkEntryPtr - &
TrainDataVector.at(0);
18495 LinkedHeadCode = (*AVEIt->NonRepeatingShuttleLinkEntryPtr).
ServiceReference;
18498 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
18500 if(LinkedHeadCode[x] ==
'/')
18502 SlashPos = LinkedHeadCode.Length() - x + 1;
18505 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
18506 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
18507 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
18513 AVEIt->NonRepeatingShuttleLinkHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
18517 AVEIt->NonRepeatingShuttleLinkHeadCode =
"";
18522 SequenceLog +=
"1\n";
18525 std::pair<AnsiString, TServiceCallingLocsList> AllServiceCallingLocsEntry;
18531 ServiceCallingLocsList.clear();
18532 if(ActionVector.empty())
18536 if(ActionVector.at(0).SignallerControl)
18540 for(
unsigned int z = 0; z < ActionVector.size(); z++)
18558 int HLoc = TE.
HLoc;
18559 int VLoc = TE.
VLoc;
18560 AnsiString HString;
18561 AnsiString VString;
18564 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18568 HString = AnsiString(HLoc);
18572 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18576 VString = AnsiString(VLoc);
18578 ServiceCallingLocsList.push_back(HString +
'-' + VString);
18601 else if(AVE.
Command ==
"cdt")
18614 ServiceCallingLocsList.push_back(
"%%%" + TimeString);
18623 ServiceCallingLocsList.push_back(LName);
18627 int HLoc = TE.
HLoc;
18628 int VLoc = TE.
VLoc;
18629 AnsiString HString;
18630 AnsiString VString;
18633 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18637 HString = AnsiString(HLoc);
18641 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18645 VString = AnsiString(VLoc);
18647 ServiceCallingLocsList.push_back(HString +
'-' + VString);
18651 AllServiceCallingLocsEntry.second = ServiceCallingLocsList;
18655 SequenceLog +=
"2\n";
18684 ShowMessage(
"Unable to create a program-readable timetable - please check the timetable file validity");
18690 bool NumPlatsAtThisLocCalculated =
false, ArrivalsPrinted =
false, DeparturesPrinted =
false, AtLocsPrinted =
false;
18691 AnsiString PreviousService =
"", PreviousServiceAndRepeatNumTotalOutput =
"", BasicTime =
"", MinuteString =
"", LastAnsiTime =
"";
18692 int NumTrains = 0, NumPlats = 0, LastFrhCount = 0, FrhCount = 0, NumTrainsAtLoc = 0;
18694 SequenceLog +=
"3\n";
18701 TDateTime LastTDTime;
18702 int IncMinutes = 0;
18704 if(ActionVector.empty())
18708 if(ActionVector.at(0).SignallerControl)
18712 if(AVLast->FormatType ==
Repeat)
18714 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
18722 if(AVLast->ArrivalTime != TDateTime(-1))
18724 LastTDTime = AVLast->ArrivalTime;
18726 else if(AVLast->EventTime != TDateTime(-1))
18728 LastTDTime = AVLast->EventTime;
18747 SequenceLog +=
"4\n";
18784 int IncMinutes = 0;
18786 if(ActionVector.empty())
18790 if(ActionVector.at(0).SignallerControl)
18794 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
18796 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
18798 for(
int y = 0; y < NumTrains; y++)
18812 for(
unsigned int z = 0; z < ActionVector.size(); z++)
18827 LocServiceTimesVector.push_back(TLSTEntry);
18830 AnsiString IncTime =
"", FoundStopTime =
"";
18831 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18833 if(ActionVector.at(a).FormatType ==
TimeLoc)
18844 if(FoundStopTime ==
"")
18846 throw Exception(
"Failure to determine FoundStopTime for located Snt");
18848 int WhileCount = 0;
18857 if(IncTime >= FoundStopTime)
18861 LocServiceTimesVector.push_back(TLSTEntry);
18862 if(WhileCount > 2000)
18864 throw Exception(
"While loop failed to break in 2000 loops for located Snt");
18877 int HLoc = TE.
HLoc;
18878 int VLoc = TE.
VLoc;
18879 AnsiString HString;
18880 AnsiString VString;
18883 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18887 HString = AnsiString(HLoc);
18891 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18895 VString = AnsiString(VLoc);
18897 TLSTEntry.
Location = HString +
'-' + VString;
18901 LocServiceTimesVector.push_back(TLSTEntry);
18909 LocServiceTimesVector.push_back(TLSTEntry);
18911 AnsiString IncTime =
"", FoundStopTime =
"";
18912 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18914 if(ActionVector.at(a).FormatType ==
TimeLoc)
18925 if(FoundStopTime ==
"")
18927 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
18929 int WhileCount = 0;
18938 if(IncTime >= FoundStopTime)
18942 LocServiceTimesVector.push_back(TLSTEntry);
18943 if(WhileCount > 2000)
18945 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
18955 bool SkipAddingMinutes =
false;
18958 LocServiceTimesVector.push_back(TLSTEntry);
18960 AnsiString IncTime =
"", FoundStopTime =
"";
18961 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18963 if(ActionVector.at(a).FormatType ==
TimeLoc)
18971 if((a <= (z + 2)) && (FoundStopTime == TLSTEntry.
ArrTime) && ((ActionVector.at(a).LinkedTrainEntryPtr != NULL) || (ActionVector.at(a).NonRepeatingShuttleLinkEntryPtr != NULL)))
18975 LocServiceTimesVector.pop_back();
18976 SkipAddingMinutes =
true;
18981 if(FoundStopTime ==
"")
18983 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
18985 if(!SkipAddingMinutes)
18987 int WhileCount = 0;
18996 if(IncTime >= FoundStopTime)
19000 LocServiceTimesVector.push_back(TLSTEntry);
19001 if(WhileCount > 2000)
19003 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
19012 if((TLSTEntry.
Location == LocServiceTimesVector.back().Location) && (TLSTEntry.
ServiceAndRepeatNum == LocServiceTimesVector.back().ServiceAndRepeatNum))
19014 if(TLSTEntry.
DepTime == LocServiceTimesVector.back().ArrTime)
19016 TLSTEntry.
ArrTime = LocServiceTimesVector.back().ArrTime;
19017 LocServiceTimesVector.pop_back();
19018 LocServiceTimesVector.push_back(TLSTEntry);
19023 LocServiceTimesVector.push_back(TLSTEntry);
19029 LocServiceTimesVector.push_back(TLSTEntry);
19048 LocServiceTimesVector.push_back(TLSTEntry);
19052 AnsiString TempDepTime = TLSTEntry.
DepTime;
19054 LocServiceTimesVector.push_back(TLSTEntry);
19056 while(TLSTEntry.
AtLocTime < TempDepTime)
19061 TLSTEntry.
DepTime = TempDepTime;
19062 LocServiceTimesVector.push_back(TLSTEntry);
19066 LocServiceTimesVector.push_back(TLSTEntry);
19077 LocServiceTimesVector.push_back(TLSTEntry);
19080 LocServiceTimesVector.push_back(TLSTEntry);
19100 AnsiString HString;
19101 AnsiString VString;
19104 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
19108 HString = AnsiString(HLoc);
19112 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
19116 VString = AnsiString(VLoc);
19118 TLSTEntry.
Location = HString +
'-' + VString;
19120 LocServiceTimesVector.push_back(TLSTEntry);
19125 AnsiString FrhTime;
19126 if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
19130 else if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
19138 LocServiceTimesVector.push_back(TLSTEntry);
19144 LocServiceTimesVector.push_back(TLSTEntry);
19149 else if(AVE.
Command ==
"Frh-sh")
19151 if(y == NumTrains - 1)
19157 LocServiceTimesVector.push_back(TLSTEntry);
19163 LocServiceTimesVector.push_back(TLSTEntry);
19176 SequenceLog +=
"5\n";
19209 TLocServiceTimesVector::iterator Ptr1, Ptr2;
19212 AnsiString TTFileName3 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
19213 TTFileName3 = CurDir +
"\\Formatted timetables\\Conflict Analysis " + TTFileName3 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
19215 std::ofstream TTFile3(TTFileName3.c_str());
19219 ShowMessage(
"Conflict Analysis file failed to open - can't be created");
19223 if(LocServiceTimesVector.empty())
19225 ShowMessage(
"No timetabled services found");
19227 DeleteFile(TTFileName3);
19231 TTFile3 <<
"Timetable analysis for timetable: '" + TimetableTitle +
"' in conjunction with railway: '" + RailwayTitle +
"'\n";
19232 TTFile3 <<
"See user manual or on-screen help section 5.12 for detailed information.\n\n\n";
19233 SequenceLog +=
"6\n";
19462 Ptr1 = LocServiceTimesVector.begin();
19464 while(Ptr2 != LocServiceTimesVector.end())
19466 while(Ptr2->Location == Ptr1->Location)
19469 if(Ptr2 == LocServiceTimesVector.end())
19476 if(Ptr2 != LocServiceTimesVector.end())
19484 TTFile3 <<
"Arrival & pass analysis: an asterisk means that the number of same approach code arrivals and passes is equal to or greater than the number of platforms.\n";
19485 TTFile3 <<
"If the total number of arrivals and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
19486 MinuteString =
" minutes";
19487 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19490 MinuteString =
" minute";
19492 TTFile3 <<
"Location,Number of,Number of,Services arriving within " << AnsiString(ArrRange) << MinuteString <<
" with their arrival times and approach codes\n";
19493 TTFile3 <<
",Platforms,Trains\n\n";
19495 Ptr1 = LocServiceTimesVector.begin();
19497 while(Ptr2 != LocServiceTimesVector.end())
19499 PreviousService =
"";
19500 NumTrainsAtLoc = 0;
19501 ServiceAndRepeatNumTotal =
"";
19503 NumPlatsAtThisLocCalculated =
false;
19505 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19507 PreviousService =
"";
19508 NumTrainsAtLoc = 0;
19509 ServiceAndRepeatNumTotal =
"";
19511 NumPlatsAtThisLocCalculated =
false;
19515 if(Ptr2 == LocServiceTimesVector.end())
19520 if(Ptr2 == LocServiceTimesVector.end())
19524 while(Ptr2->Location == Ptr1->Location)
19526 PreviousService =
"";
19527 NumTrainsAtLoc = 0;
19528 ServiceAndRepeatNumTotal =
"";
19529 BasicTime = Ptr1->ArrTime;
19530 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19534 while(!
WithinTimeRange(0, BasicTime, Ptr2->ArrTime, ArrRange) || ((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
"")))
19536 BasicTime = Ptr2->ArrTime;
19539 if(Ptr2 == LocServiceTimesVector.end())
19543 if(Ptr2->Location != Ptr1->Location)
19548 if(Ptr2 == LocServiceTimesVector.end())
19552 if(Ptr2->Location != Ptr1->Location)
19558 if((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
""))
19562 if(!NumPlatsAtThisLocCalculated)
19565 NumPlatsAtThisLocCalculated =
true;
19567 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19569 if(ServiceAndRepeatNumTotal ==
"")
19571 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
19572 NumTrainsAtLoc = 1;
19576 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
19579 PreviousService = Ptr2->ServiceAndRepeatNum;
19580 if(ServiceAndRepeatNumTotal ==
"")
19582 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
19583 NumTrainsAtLoc = 1;
19587 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
19591 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(2, BasicTime, Ptr2->ArrTime, ArrRange)))
19593 int MaxNumberOfSameDirections = 0;
19594 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
true, AnalysisError, MaxNumberOfSameDirections);
19599 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
19603 AnsiString Asterisk =
"";
19604 if(MaxNumberOfSameDirections >= NumPlats)
19609 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19610 ArrivalsPrinted =
true;
19611 ServiceAndRepeatNumTotal =
"";
19613 if(Ptr2 == LocServiceTimesVector.end())
19617 if(Ptr2->Location != Ptr1->Location)
19622 if(Ptr2 == LocServiceTimesVector.end())
19628 if(!ArrivalsPrinted)
19630 TTFile3 <<
"Nothing to report for arrivals";
19635 SequenceLog +=
"7\n";
19640 Ptr1 = LocServiceTimesVector.begin();
19642 while(Ptr2 != LocServiceTimesVector.end())
19644 while(Ptr2->Location == Ptr1->Location)
19647 if(Ptr2 == LocServiceTimesVector.end())
19654 if(Ptr2 != LocServiceTimesVector.end())
19661 TTFile3 <<
"Departure & pass analysis: an asterisk means that the number of same exit code departures and passes is equal to or greater than the number of platforms.\n";
19662 TTFile3 <<
"If the total number of departures and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
19663 MinuteString =
" minutes";
19664 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19667 MinuteString =
" minute";
19669 TTFile3 <<
"Location,Number of,Number of,Services departing within " << AnsiString(DepRange) << MinuteString <<
" with their departure times and exit codes\n";
19670 TTFile3 <<
",Platforms,Trains\n\n";
19672 Ptr1 = LocServiceTimesVector.begin();
19674 while(Ptr2 != LocServiceTimesVector.end())
19676 PreviousService =
"";
19677 NumTrainsAtLoc = 0;
19678 ServiceAndRepeatNumTotal =
"";
19680 NumPlatsAtThisLocCalculated =
false;
19682 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19684 PreviousService =
"";
19685 NumTrainsAtLoc = 0;
19686 ServiceAndRepeatNumTotal =
"";
19688 NumPlatsAtThisLocCalculated =
false;
19692 if(Ptr2 == LocServiceTimesVector.end())
19697 if(Ptr2 == LocServiceTimesVector.end())
19701 while(Ptr2->Location == Ptr1->Location)
19703 PreviousService =
"";
19704 NumTrainsAtLoc = 0;
19705 ServiceAndRepeatNumTotal =
"";
19706 BasicTime = Ptr1->DepTime;
19707 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19711 while(!
WithinTimeRange(3, BasicTime, Ptr2->DepTime, DepRange) || ((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
"")))
19713 BasicTime = Ptr2->DepTime;
19716 if(Ptr2 == LocServiceTimesVector.end())
19720 if(Ptr2->Location != Ptr1->Location)
19725 if(Ptr2 == LocServiceTimesVector.end())
19729 if(Ptr2->Location != Ptr1->Location)
19735 if((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
""))
19739 if(!NumPlatsAtThisLocCalculated)
19742 NumPlatsAtThisLocCalculated =
true;
19744 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19746 if(ServiceAndRepeatNumTotal ==
"")
19748 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
19749 NumTrainsAtLoc = 1;
19753 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
19756 PreviousService = Ptr2->ServiceAndRepeatNum;
19757 if(ServiceAndRepeatNumTotal ==
"")
19759 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
19760 NumTrainsAtLoc = 1;
19764 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
19768 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(5, BasicTime, Ptr2->DepTime, DepRange)))
19770 int MaxNumberOfSameDirections = 0;
19771 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(3, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
false, AnalysisError, MaxNumberOfSameDirections);
19776 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
19780 AnsiString Asterisk =
"";
19781 if(MaxNumberOfSameDirections >= NumPlats)
19786 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19787 DeparturesPrinted =
true;
19788 ServiceAndRepeatNumTotal =
"";
19790 if(Ptr2 == LocServiceTimesVector.end())
19794 if(Ptr2->Location != Ptr1->Location)
19799 if(Ptr2 == LocServiceTimesVector.end())
19805 if(!DeparturesPrinted)
19807 TTFile3 <<
"Nothing to report for departures";
19812 SequenceLog +=
"8\n";
19819 Ptr1 = LocServiceTimesVector.begin();
19821 while(Ptr2 != LocServiceTimesVector.end())
19823 while(Ptr2->Location == Ptr1->Location)
19826 if(Ptr2 == LocServiceTimesVector.end())
19833 if(Ptr2 != LocServiceTimesVector.end())
19840 TTFile3 <<
"Trains present at location analysis: an asterisk means that the number of trains at the location is greater than the number of platforms.\n\n";
19841 TTFile3 <<
"Location,Number of,Number of,Time,Services at the location at that time\n";
19842 TTFile3 <<
",Platforms,Trains,\n\n";
19843 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19844 Ptr1 = LocServiceTimesVector.begin();
19846 while(Ptr2 != LocServiceTimesVector.end())
19848 PreviousService =
"";
19849 ServiceAndRepeatNumTotal =
"";
19850 NumTrainsAtLoc = 0;
19852 NumPlatsAtThisLocCalculated =
false;
19855 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19857 PreviousService =
"";
19858 ServiceAndRepeatNumTotal =
"";
19859 NumTrainsAtLoc = 0;
19861 NumPlatsAtThisLocCalculated =
false;
19865 if(Ptr2 == LocServiceTimesVector.end())
19870 if(Ptr2 == LocServiceTimesVector.end())
19874 while(Ptr2->Location == Ptr1->Location)
19876 if(Ptr1->FrhMarker ==
"Frh")
19879 Ptr1->FrhMarker =
"FrhCounted";
19881 PreviousService =
"";
19882 NumTrainsAtLoc = 0;
19883 ServiceAndRepeatNumTotal =
"";
19884 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19888 while((Ptr2->AtLocTime != Ptr1->AtLocTime) || ((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
"")))
19891 if(Ptr1->FrhMarker ==
"Frh")
19894 Ptr1->FrhMarker =
"FrhCounted";
19897 if(Ptr2 == LocServiceTimesVector.end())
19901 if(Ptr2->Location != Ptr1->Location)
19906 if(Ptr2 == LocServiceTimesVector.end())
19910 if(Ptr2->Location != Ptr1->Location)
19914 while(Ptr2->AtLocTime == Ptr1->AtLocTime)
19916 if((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
""))
19920 if(!NumPlatsAtThisLocCalculated)
19923 NumPlatsAtThisLocCalculated =
true;
19925 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19927 if(ServiceAndRepeatNumTotal ==
"")
19929 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum;
19930 NumTrainsAtLoc = 1;
19934 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum;
19937 PreviousService = Ptr2->ServiceAndRepeatNum;
19938 if(ServiceAndRepeatNumTotal ==
"")
19940 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum;
19941 NumTrainsAtLoc = 1;
19945 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum;
19948 if(Ptr1->FrhMarker ==
"Frh")
19951 Ptr1->FrhMarker =
"FrhCounted";
19954 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (Ptr2->AtLocTime != Ptr1->AtLocTime))
19958 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTAtLoc(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc);
19960 if((NumTrainsAtLoc > 1) && ((FrhCount < NumTrainsAtLoc) || (FrhCount != LastFrhCount)))
19962 AnsiString Asterisk =
"";
19963 if(NumTrainsAtLoc > NumPlats)
19970 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19972 else if(FrhCount == 1)
19974 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (1 remains here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
19978 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (" << FrhCount <<
" remain here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
19980 LastFrhCount = FrhCount;
19981 PreviousServiceAndRepeatNumTotalOutput = ServiceAndRepeatNumTotalOutput;
19982 AtLocsPrinted =
true;
19983 ServiceAndRepeatNumTotal =
"";
19986 if(Ptr2 == LocServiceTimesVector.end())
19990 if(Ptr2->Location != Ptr1->Location)
19995 if(Ptr2 == LocServiceTimesVector.end())
20003 TTFile3 <<
"Nothing to report for trains at locations";
20008 SequenceLog +=
"9\n";
20042 TTrainDataEntry SingleServiceEntry, PartServiceEntry, NewPartServiceEntry, TempEntry;
20047 TTFile3 <<
"Train direction analysis - consisting of train facing directions on creation and possible missing or questionable changes of direction:\n\n";
20056 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
20058 SingleServiceEntry = TDE;
20060 for(
unsigned int y = 0; y < SSAV.size(); y++)
20062 if((SSAV.at(y).Command ==
"Fjo") || (SSAV.at(y).Command ==
"Frh") || (SSAV.at(y).Command ==
"Fer") || (SSAV.at(y).Command ==
"Frh-sh"))
20064 SingleServiceVector.push_back(SingleServiceEntry);
20067 else if((SSAV.at(y).Command ==
"fsp") || (SSAV.at(y).Command ==
"rsp"))
20069 PartServiceEntry = TDE;
20071 for(
unsigned int z = 0; z <= y; z++)
20076 PartServiceEntry.
ActionVector.at(z).Command =
"chr-sp";
20077 PartServiceEntry.
ActionVector.at(z).OtherHeadCode = PartServiceEntry.
ActionVector.at(z).LinkedTrainEntryPtr->ServiceReference;
20080 PartServiceVector.push_back(PartServiceEntry);
20081 if(SSAV.at(y).Command ==
"fsp")
20083 SSAV.at(y).Command =
"Front split - original service continues below";
20084 SSAV.at(y).OtherHeadCode =
"";
20086 if(SSAV.at(y).Command ==
"rsp")
20088 SSAV.at(y).Command =
"Rear split - original service continues below";
20089 SSAV.at(y).OtherHeadCode =
"";
20093 else if(SSAV.at(y).Command ==
"Fns")
20095 SSAV.at(y).Command =
"chr-Fns";
20096 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
20097 PartServiceVector.push_back(SingleServiceEntry);
20100 else if(SSAV.at(y).Command ==
"Fns-sh")
20102 SSAV.at(y).Command =
"chr-Fns-sh";
20103 SSAV.at(y).OtherHeadCode = SSAV.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
20104 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
20105 PartServiceVector.push_back(SingleServiceEntry);
20108 else if(SSAV.at(y).Command ==
"F-nshs")
20110 SSAV.at(y).Command =
"chr-F-nshs";
20111 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
20112 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
20113 PartServiceVector.push_back(SingleServiceEntry);
20119 SequenceLog +=
"10\n";
20123 AnsiString NextRef;
20124 while(!PartServiceVector.empty())
20126 PartServiceEntry = PartServiceVector.at(0);
20127 for(
unsigned int y = 0; y < PartServiceEntry.
ActionVector.size(); y++)
20129 if(PartServiceEntry.
ActionVector.at(y).Command.SubString(1,3) ==
"chr")
20131 NextRef = PartServiceEntry.
ActionVector.at(y).OtherHeadCode;
20135 bool FinishType =
true, FoundFlag =
false;
20142 for(
unsigned int y = 1; y < TempEntry.
ActionVector.size(); y++)
20146 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
20150 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
20156 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
20157 SingleServiceVector.push_back(PartServiceVector.at(0));
20158 PartServiceVector.erase(PartServiceVector.begin());
20163 NewPartServiceEntry = PartServiceVector.at(0);
20167 PartServiceVector.push_back(NewPartServiceEntry);
20170 TempEntry.
ActionVector.at(y).Command =
"Front split - original service continues below";
20175 TempEntry.
ActionVector.at(y).Command =
"Rear split - original service continues below";
20178 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
20180 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns")
20183 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
20185 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
20188 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns-sh")
20191 TempEntry.
ActionVector.at(y).OtherHeadCode = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
20192 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
20193 NextRef = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
20194 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
20197 else if(TempEntry.
ActionVector.at(y).Command ==
"F-nshs")
20201 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
20202 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
20203 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
20211 SequenceLog += +
"11\n";
20212 throw Exception(
"Unable to find service reference " + NextRef +
" Last ref checked = " + TempEntry.
ServiceReference);
20216 if(!PartServiceVector.empty())
20218 SequenceLog +=
"12\n";
20219 throw Exception(
"PartServiceVector should be empty here - size = " + AnsiString(PartServiceVector.size()));
20221 SequenceLog +=
"13\n";
20270 bool BufferFacingUnReportedFlag =
true;
20271 bool TrainFacingBuffersReported =
false;
20272 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
20278 SequenceLog +=
"13a\n";
20279 throw Exception(
"Repeat entry present in SingleServiceVector at position " + AnsiString(x));
20282 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
20284 bool BufferFlag =
false;
20285 int FrontTVPos = AV.at(0).FrontStartOrRepeatDigits;
20286 int RearTVPos = AV.at(0).RearStartOrRepeatMins;
20287 AnsiString FrontLocName = AV.at(0).LocationName;
20288 int NextEntryPos, NextExitPos;
20291 if(ThisElement.
Conn[0] == RearTVPos)
20295 else if(ThisElement.
Conn[1] == RearTVPos)
20299 else if(ThisElement.
Conn[2] == RearTVPos)
20303 else if(ThisElement.
Conn[3] == RearTVPos)
20315 if(ThisElement.
Conn[ThisExitPos] == -1)
20317 SequenceLog =
"13b\n";
20318 throw Exception(
"ThisElement connects to -1 for " + TDE.
ServiceReference);
20321 NextEntryPos = ThisElement.
ConnLinkPos[ThisExitPos];
20322 if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 0) || (NextEntryPos == 2)))
20324 BufferFlag =
false;
20329 BufferFlag =
false;
20334 BufferFlag =
false;
20342 else if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 1) || (NextEntryPos == 3)))
20344 ThisElement = NextElement;
20350 if(NextEntryPos == 0)
20354 else if(NextEntryPos == 1)
20358 else if(NextEntryPos == 2)
20362 else if(NextEntryPos == 3)
20367 ThisElement = NextElement;
20368 ThisExitPos = NextExitPos;
20373 if(BufferFacingUnReportedFlag)
20375 TTFile3 <<
"Train facing direction on creation analysis:-\n\n";
20376 BufferFacingUnReportedFlag =
false;
20378 if(AV.at(1).Command !=
"cdt")
20380 TTFile3 <<
"Service " + TDE.
ServiceReference +
" facing buffers on creation with no immediate change of direction\n";
20381 TrainFacingBuffersReported =
true;
20386 if(!TrainFacingBuffersReported)
20388 TTFile3 <<
"Nothing to report for train facing directions\n\n";
20394 SequenceLog +=
"13c\n";
20397 AnsiString LocationNameToBeChecked =
"";
20398 bool MissingcdtUnreportedFlag =
true;
20400 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
20403 unsigned int y = 0;
20404 int FirstInstance = 9999, SecondInstance = 9999;
20405 bool FullBreak =
false;
20406 MarkerList.clear();
20408 while((y < TDEntry.
ActionVector.size()) && !FullBreak)
20417 LocationNameToBeChecked =
"";
20423 if(LocationNameToBeChecked ==
"")
20430 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
20433 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
20438 (AVEntry.
Command ==
"Frh-sh"))
20453 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
20455 AnsiString LocationName;
20462 int ExitLoc = TDEntry.
ActionVector.at(a).ExitList.front();
20467 LocationName = TDEntry.
ActionVector.at(a).LocationName;
20469 if(LocationName == LocationNameToBeChecked)
20471 SecondInstance = a;
20473 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
20475 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
20477 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
20480 if(MissingcdtUnreportedFlag)
20482 TTFile3 <<
"Possibly missing changes of direction - these will be missing unless the service travels in a loop back to the locations marked:-\n\n";
20484 TTFile3 << LocationNameToBeChecked <<
" is listed twice with no direction change between in service sequence: " << Sequence <<
"\n\n";
20485 MarkerList.push_back(FirstInstance);
20486 MarkerList.push_back(SecondInstance);
20488 MissingcdtUnreportedFlag =
false;
20499 if(MissingcdtUnreportedFlag)
20501 TTFile3 <<
"Nothing to report for missing changes of direction\n\n";
20507 SequenceLog +=
"14\n";
20516 typedef std::list<AnsiString> TLocList;
20517 TLocList BackwardList, ForwardList;
20518 bool IntroLineNeeded =
true;
20519 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
20521 unsigned int cdtPosition = 9999;
20522 AnsiString cdtLocation =
"";
20523 bool FoundSameName =
false;
20524 bool FerEntry =
false;
20525 MarkerList.clear();
20527 for(
unsigned int y = 0; y <= TDEntry.
ActionVector.size(); y++)
20534 BackwardList.clear();
20535 ForwardList.clear();
20536 bool ValidEnd =
false;
20542 (AVEntry.
Command ==
"Frh-sh"))
20547 if(FerEntry || ValidEnd)
20549 if(MarkerList.empty())
20556 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
20558 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
20560 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
20564 if(IntroLineNeeded)
20566 TTFile3 <<
"Questionable change of direction analysis.\n\n";
20567 TTFile3 <<
"For marked changes of direction there are no same-name locations listed both above (up to the start or another direction change)\n";
20568 TTFile3 <<
"and below (down to the end or another direction change) but not counting the change of direction location itself.\n\n";
20569 TTFile3 <<
"These changes of direction are probably valid for movements to and from depots but all should be checked to\n";
20570 TTFile3 <<
"make sure that none has been included incorrectly:\n\n";
20571 IntroLineNeeded =
false;
20573 TTFile3 <<
"Service sequence " << Sequence <<
" contains questionable changes of direction:-\n\n";
20588 for(
int z = y - 1; z >= 0; z--)
20591 if(AVEntry2.
Command ==
"cdt")
20595 AnsiString LocName =
"";
20605 if((LocName !=
"") && (AVEntry2.
LocationName != cdtLocation))
20607 BackwardList.push_back(LocName);
20610 BackwardList.sort();
20611 BackwardList.unique();
20612 for(
unsigned int z = y + 1; z < TDEntry.
ActionVector.size(); z++)
20621 AnsiString LocName =
"";
20622 if(AVEntry3.
Command ==
"Fer")
20624 int ExitLoc = AVEntry3.
ExitList.front();
20632 if((LocName !=
"") && (AVEntry3.
LocationName != cdtLocation))
20634 ForwardList.push_back(LocName);
20637 ForwardList.sort();
20638 ForwardList.unique();
20639 FoundSameName =
false;
20641 if(!BackwardList.empty() && !ForwardList.empty())
20643 for(TLocList::iterator BLIt = BackwardList.begin(); BLIt != BackwardList.end(); BLIt++)
20645 for(TLocList::iterator FLIt = ForwardList.begin(); FLIt != ForwardList.end(); FLIt++)
20649 FoundSameName =
true;
20656 MarkerList.push_back(cdtPosition);
20661 if(IntroLineNeeded)
20663 TTFile3 <<
"Nothing to report for questionable changes of direction\n\n";
20681 SequenceLog +=
"15\n";
20687 catch(
const Exception &e)
20689 AnsiString TTErrorFileName =
"Analysis Error.txt";
20690 TTErrorFileName = CurDir +
"\\Formatted timetables\\" + TTErrorFileName;
20691 std::ofstream TTError(TTErrorFileName.c_str());
20694 ShowMessage(
"Analysis error file failed to open - can't be created");
20698 AnsiString TimeNow = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
20699 TTError << TimeNow.c_str() <<
'\n' << ArrRange <<
'\n' << ArrChecked <<
'\n' << DepRange <<
'\n' <<
20700 DepChecked <<
'\n' << AtLocChecked <<
'\n' << SequenceLog <<
'\n' << AnsiString(e.Message);
20703 ShowMessage(
"Error in Conflict Analysis: A file called 'Analysis Error.txt' has been created in your Formatted timetables folder. Please send this file together with your railway and timetable files to railwayfeedback@gmail.com for investigation - many thanks");
20713 if((SSVectorNumber < 0) || ((
unsigned int)SSVectorNumber >= SingleServiceVector.size()))
20715 throw Exception(
"SSVectorNumber out of range, = " + AnsiString(SSVectorNumber) +
", Vector size = " + SingleServiceVector.size());
20717 TTrainDataEntry SingleService = SingleServiceVector.at(SSVectorNumber);
20719 VecFile <<
",Initial service reference " << SingleService.
ServiceReference +
'\n';
20720 AnsiString Marker =
"";
20721 for(
unsigned int x = 0; x < SingleService.
ActionVector.size(); x++)
20724 for(
TNumListIterator MLIt = MarkerList.begin(); MLIt != MarkerList.end(); MLIt++)
20726 if(
int(x) == *MLIt)
20756 if(AVE.
Command.SubString(1,3) ==
"chr")
20765 AVE.
Command =
"Change of service to ";
20767 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"Fns-sh")
20769 AVE.
Command =
"Change to shuttle finishing service";
20771 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"F-nshs")
20798 AnsiString ListOfExits =
"";
20807 VecFile << Marker <<
"Frh" <<
'\n';
20822 for(
unsigned int x = 0; x < Vector.size(); x++)
20825 if(Vector.at(x).ServiceReference == HeadCode)
20827 if(Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1).FormatType ==
Repeat)
20829 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 2);
20832 FinishType =
false;
20837 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1);
20840 FinishType =
false;
20845 return(Vector.at(x));
20849 return(Vector.at(Vector.size() - 1));
20858 if((Time1 ==
"") || (Time2 ==
""))
20863 int Mins = Time1.SubString(4,2).ToInt();
20864 int Hours = Time1.SubString(1,2).ToInt();
20865 int Time1Mins = (Hours * 60) + Mins;
20866 Mins = Time2.SubString(4,2).ToInt();
20867 Hours = Time2.SubString(1,2).ToInt();
20868 int Time2Mins = (Hours * 60) + Mins;
20869 if(abs(Time1Mins - Time2Mins) <= MinuteRange)
20881 bool &AnalysisError,
int &MaxNumberOfSameDirections)
20888 AnsiString Output =
"", OneService =
"", TempStr1 =
"", TempStr2 =
"";
20890 std::list<AnsiString> ServiceList;
20892 bool EvenComma =
false;
20893 for(
int x = 1; x <= Input.Length(); x++)
20895 TempStr1 = Input[x];
20896 if(TempStr1 == AnsiString(
',') && EvenComma)
20902 TempStr2 += Input[x];
20904 if(TempStr1 == AnsiString(
','))
20906 EvenComma = !EvenComma;
20910 while(TempStr2.Length() > 0)
20912 SCPos = TempStr2.Pos(
';');
20915 OneService = TempStr2.SubString(1, SCPos - 1);
20916 ServiceList.push_back(OneService);
20917 TempStr2 = TempStr2.SubString(SCPos + 1, TempStr2.Length() - SCPos);
20921 ServiceList.push_back(TempStr2);
20925 ServiceList.sort();
20926 ServiceList.unique();
20927 NumTrainsAtLoc = ServiceList.size();
20930 int DirectionMarker = 0;
20932 std::list<AnsiString>::iterator SLIt, SLIt1, SLIt2, SLIt3;
20934 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20936 *SLIt = *SLIt +
"&0";
20938 SLIt3 = ServiceList.end();
20940 AnsiString ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatInfo1, RepeatInfo2;
20941 int AmpersandPos, SpacePos, CommaPos1, CommaPos2, RepeatNum1, RepeatNum2;
20942 TAllServiceCallingLocsMap::iterator ASCLIt1, ASCLIt2;
20944 MaxNumberOfSameDirections = 0;
20945 int SameDirectionCount = 0;
20947 for(std::list<AnsiString>::iterator SLIt1 = ServiceList.begin(); SLIt1 != SLIt3; SLIt1++)
20951 if(SLIt1->SubString(SLIt1->Length() - 1, 2) != AnsiString(
"&0"))
20957 CommaPos1 = SLIt1->Pos(
',');
20958 ServiceRef1 = SLIt1->SubString(1, CommaPos1 - 1);
20960 SpacePos = ServiceRef1.Pos(
' ');
20964 RepeatInfo1 = ServiceRef1.SubString(SpacePos + 2, ServiceRef1.Length() - SpacePos - 2);
20965 ServiceRef1 = ServiceRef1.SubString(1, SpacePos - 1);
20966 if(RepeatInfo1[1] ==
'F')
20972 SpacePos = RepeatInfo1.Pos(
' ');
20973 RepeatNum1 = RepeatInfo1.SubString(SpacePos + 1, RepeatInfo1.Length() - SpacePos).ToInt();
20976 AnsiTime1 = SLIt1->SubString(CommaPos1 + 1, SLIt1->Length() - CommaPos1);
20978 AmpersandPos = AnsiTime1.Pos(
'&');
20979 AnsiTime1 = AnsiTime1.SubString(1, AmpersandPos - 1);
20984 throw Exception(
"ASCLIt1 Error in " + Input);
20986 ServiceCallingLocsList1 = ASCLIt1->second;
20987 AmpersandPos = SLIt1->Pos(
'&');
20988 *SLIt1 = SLIt1->SubString(1, AmpersandPos);
20989 *SLIt1 = *SLIt1 + AnsiString(++DirectionMarker);
20991 SameDirectionCount = 1;
20992 for(SLIt2 = SLIt; SLIt2 != ServiceList.end(); SLIt2++)
20994 CommaPos2 = SLIt2->Pos(
',');
20995 ServiceRef2 = SLIt2->SubString(1, CommaPos2 - 1);
20997 SpacePos = ServiceRef2.Pos(
' ');
21001 RepeatInfo2 = ServiceRef2.SubString(SpacePos + 2, ServiceRef2.Length() - SpacePos - 2);
21002 ServiceRef2 = ServiceRef2.SubString(1, SpacePos - 1);
21003 if(RepeatInfo2[1] ==
'F')
21009 SpacePos = RepeatInfo2.Pos(
' ');
21010 RepeatNum2 = RepeatInfo2.SubString(SpacePos + 1, RepeatInfo2.Length() - SpacePos).ToInt();
21013 AnsiTime2 = SLIt2->SubString(CommaPos2 + 1, SLIt2->Length() - CommaPos2);
21015 AmpersandPos = AnsiTime2.Pos(
'&');
21016 AnsiTime2 = AnsiTime2.SubString(1, AmpersandPos - 1);
21021 throw Exception(
"ASCLIt2 Error in " + Input);
21023 ServiceCallingLocsList2 = ASCLIt2->second;
21025 if(
SameDirection(0, ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatNum1, RepeatNum2, ServiceCallingLocsList1, ServiceCallingLocsList2, Location, Arrival))
21027 int AmpersandPos = SLIt2->Pos(
'&');
21028 *SLIt2 = SLIt2->SubString(1, AmpersandPos);
21029 *SLIt2 = *SLIt2 + AnsiString(DirectionMarker);
21030 SameDirectionCount++;
21033 if(SameDirectionCount > MaxNumberOfSameDirections)
21035 MaxNumberOfSameDirections = SameDirectionCount;
21040 if(SLIt3->SubString(SLIt3->Length() - 1, 2) == AnsiString(
"&0"))
21043 AmpersandPos = SLIt3->Pos(
'&');
21044 *SLIt3 = SLIt3->SubString(1, AmpersandPos);
21045 *SLIt3 = *SLIt3 + AnsiString(++DirectionMarker);
21048 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
21051 AmpersandPos = SLIt->Pos(
'&');
21052 AnsiString DirectionMarkerString = SLIt->SubString(AmpersandPos + 1, SLIt->Length() - AmpersandPos);
21053 AnsiString ServiceWithoutMarker = SLIt->SubString(1, AmpersandPos - 1);
21054 DirectionMarker = DirectionMarkerString.ToInt();
21055 AnsiString DirectionSuffix =
"";
21057 if(DirectionMarker < 27)
21059 c = 64 + DirectionMarker;
21060 DirectionSuffix =
"," + AnsiString(c);
21062 else if(DirectionMarker < 53)
21064 c = 65 + DirectionMarker - 27;
21065 DirectionSuffix =
",A" + AnsiString(c);
21069 DirectionSuffix =
",?";
21071 *SLIt = ServiceWithoutMarker + DirectionSuffix;
21074 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
21076 Output = Output + *SLIt +
",";
21078 if(Output.Length() > 0)
21080 Output = Output.SubString(1, Output.Length() - 1);
21086 catch(
const Exception &e)
21088 AnalysisError =
true;
21100 AnsiString InternalInput = Input, Output =
"", OneService =
"";
21102 std::list<AnsiString> ServiceList;
21104 while(InternalInput.Length() > 0)
21106 CommaPos = InternalInput.Pos(
',');
21109 OneService = InternalInput.SubString(1, CommaPos - 1);
21110 ServiceList.push_back(OneService);
21111 InternalInput = InternalInput.SubString(CommaPos + 1, InternalInput.Length() - CommaPos);
21115 ServiceList.push_back(InternalInput);
21116 InternalInput =
"";
21120 ServiceList.sort();
21121 ServiceList.unique();
21122 NumTrainsAtLoc = ServiceList.size();
21123 for(std::list<AnsiString>::iterator SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
21125 Output = Output + *SLIt +
",";
21127 if(Output.Length() > 0)
21129 Output = Output.SubString(1, Output.Length() - 1);
21142 AnsiString(RepeatNum1) +
"," + AnsiString(RepeatNum2) +
"," + Location);
21144 std::list<AnsiString>::iterator LP1, LP2, ListPtr1, ListPtr2, LocPtr1, LocPtr2;
21149 bool LocFound =
false;
21150 AnsiString Ref1 = Ref1In, Ref2 = Ref2In;
21152 TDateTime FirstServiceTime;
21155 int Ref1Target = 0, Ref1Count = 0;
21156 int Ref2Target = 0, Ref2Count = 0;
21174 for(ListPtr1 = List1.begin(); ListPtr1 != List1.end(); ListPtr1++)
21177 if((*ListPtr1) == Location)
21179 LocPtr1 = ListPtr1;
21182 if(ListPtr1->SubString(1, 3) ==
"%%%")
21184 AnsiString CDTTime = ListPtr1->SubString(4, 5);
21189 FirstServiceTime = TDateTime(-1);
21190 bool BreakFlag =
false;
21193 if(TDVIt->ServiceReference == Ref1)
21195 if(Ref1Target > Ref1Count)
21200 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
21201 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
21205 FirstServiceTime = AVIt->EventTime;
21211 FirstServiceTime = AVIt->ArrivalTime;
21217 FirstServiceTime = AVIt->DepartureTime;
21228 if(IncMinutes == -1)
21230 throw Exception(
"Failed to find service for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
21232 if(FirstServiceTime == TDateTime(-1))
21234 throw Exception(
"Failed to find first service time for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
21238 if(!Arrival && (Time1 == CDTTime))
21243 if(Arrival && (Time1 == CDTTime))
21247 if(Time1 > CDTTime)
21252 if(Time1 < CDTTime)
21265 for(ListPtr2 = List2.begin(); ListPtr2 != List2.end(); ListPtr2++)
21267 if((*ListPtr2) == Location)
21269 LocPtr2 = ListPtr2;
21272 if(ListPtr2->SubString(1, 3) ==
"%%%")
21274 AnsiString CDTTime = ListPtr2->SubString(4, 5);
21279 FirstServiceTime = TDateTime(-1);
21280 bool BreakFlag =
false;
21283 if(TDVIt->ServiceReference == Ref2)
21285 if(Ref2Target > Ref2Count)
21290 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
21291 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
21295 FirstServiceTime = AVIt->EventTime;
21301 FirstServiceTime = AVIt->ArrivalTime;
21307 FirstServiceTime = AVIt->DepartureTime;
21318 if(IncMinutes == -1)
21320 throw Exception(
"IncMinutes -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
21322 if(FirstServiceTime == TDateTime(-1))
21324 throw Exception(
"First service time -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
21328 if(!Arrival && (Time2 == CDTTime))
21333 if(Arrival && (Time2 == CDTTime))
21337 if(Time2 > CDTTime)
21342 if(Time2 < CDTTime)
21357 LP1 = List1.begin();
21359 for(ListPtr1 = LocPtr1; ListPtr1 != LP1; ListPtr1--)
21361 if(ListPtr1 == List1.begin())
21365 if(ListPtr1->SubString(1, 3) ==
"%%%")
21372 LP2 = List2.begin();
21374 for(ListPtr2 = LocPtr2; ListPtr2 != LP2; ListPtr2--)
21376 if(ListPtr2 == List2.begin())
21380 if(ListPtr2->SubString(1, 3) ==
"%%%")
21390 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
21392 if(ListPtr1 == LocPtr1)
21396 if(ListPtr1->SubString(1, 3) ==
"%%%")
21400 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
21402 if(ListPtr2 == LocPtr2)
21406 if(ListPtr2->SubString(1, 3) ==
"%%%")
21410 if((*ListPtr1) == (*ListPtr2))
21427 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
21429 if(ListPtr1 == List1.end())
21433 if(ListPtr1->SubString(1, 3) ==
"%%%")
21437 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
21439 if(ListPtr2 == List2.end())
21443 if(ListPtr2->SubString(1, 3) ==
"%%%")
21447 if((*ListPtr1) == (*ListPtr2))
21464 if(ExitList.empty())
21470 AnsiString ExitLocList =
"";
21473 unsigned int Counter = 0;
21474 for(
TNumListIterator ELIt = ExitList.begin(); ELIt != ExitList.end(); ELIt++)
21478 if(((Counter % 6) == 0) && (Counter < (ExitList.size() - 1)))
21480 ExitLocList +=
"\n";
21483 if(StartName ==
"")
21485 if(ExitList.size() == 1)
21489 return(
" at " + ID);
21494 if(ExitList.size() < 4)
21496 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
21501 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21506 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
21511 if(ExitList.size() < 4)
21513 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
21518 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21524 if(ExitList.size() < 4)
21526 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
21527 return(
" at " + StartName);
21531 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21532 return(
" at " + StartName);
21572 AnsiString FormatStr =
"####0.0";
21573 AnsiString AvLateArrMins =
"";
21574 AnsiString AvEarlyArrMins =
"";
21575 AnsiString AvLatePassMins =
"";
21576 AnsiString AvEarlyPassMins =
"";
21577 AnsiString AvLateDepMins =
"";
21578 AnsiString AvLateExitMins =
"";
21579 AnsiString AvEarlyExitMins =
"";
21582 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21615 PerfFile <<
'\n' <<
'\n' <<
"***************************************";
21616 PerfFile <<
'\n' <<
'\n' <<
"Performance summary:" <<
'\n';
21628 PerfFile <<
LateArrivals <<
" late arrivals (average " << AvLateArrMins.c_str() <<
" min)" <<
'\n';
21632 PerfFile <<
LateArrivals <<
" late arrival (" << AvLateArrMins.c_str() <<
" min)" <<
'\n';
21640 PerfFile <<
EarlyArrivals <<
" early arrivals (average " << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
21644 PerfFile <<
EarlyArrivals <<
" early arrival (" << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
21652 PerfFile <<
OnTimePasses <<
" on-time passes" <<
'\n';
21660 PerfFile <<
LatePasses <<
" late passes (average " << AvLatePassMins.c_str() <<
" min)" <<
'\n';
21664 PerfFile <<
LatePasses <<
" late pass (" << AvLatePassMins.c_str() <<
" min)" <<
'\n';
21668 PerfFile <<
LatePasses <<
" late passes" <<
'\n';
21672 PerfFile <<
EarlyPasses <<
" early passes (average " << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
21676 PerfFile <<
EarlyPasses <<
" early pass (" << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
21680 PerfFile <<
EarlyPasses <<
" early passes" <<
'\n';
21685 PerfFile <<
OnTimeExits <<
" on-time exits" <<
'\n';
21689 PerfFile <<
OnTimeExits <<
" on-time exit" <<
'\n';
21693 PerfFile <<
LateExits <<
" late exits (average " << AvLateExitMins.c_str() <<
" min)" <<
'\n';
21697 PerfFile <<
LateExits <<
" late exit (" << AvLateExitMins.c_str() <<
" min)" <<
'\n';
21701 PerfFile <<
LateExits <<
" late exits" <<
'\n';
21705 PerfFile <<
EarlyExits <<
" early exits (average " << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
21709 PerfFile <<
EarlyExits <<
" early exit (" << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
21713 PerfFile <<
EarlyExits <<
" early exits" <<
'\n';
21718 PerfFile <<
OnTimeDeps <<
" on-time departures" <<
'\n';
21722 PerfFile <<
OnTimeDeps <<
" on-time departure" <<
'\n';
21726 PerfFile <<
LateDeps <<
" late departures (average " << AvLateDepMins.c_str() <<
" min)" <<
'\n';
21730 PerfFile <<
LateDeps <<
" late departure (" << AvLateDepMins.c_str() <<
" min)" <<
'\n';
21734 PerfFile <<
LateDeps <<
" late departures" <<
'\n';
21736 TDateTime TempExcessLCDownTime;
21750 if(TempExcessLCDownTime > TDateTime(0))
21756 AnsiString FormattedExcessLCDownMins = FormatFloat(FormatStr,
ExcessLCDownMins);
21760 PerfFile << FormattedExcessLCDownMins.c_str() <<
" excess minutes of level crossing barrier down time" <<
'\n';
21772 PerfFile <<
MissedStops <<
" missed stops" <<
'\n';
21776 PerfFile <<
MissedStops <<
" missed stop" <<
'\n';
21812 PerfFile <<
NumFailures <<
" train failures" <<
'\n';
21816 PerfFile <<
NumFailures <<
" train failure" <<
'\n';
21822 PerfFile <<
AvHoursIntValue <<
" hour mean time betweeen train failures" <<
'\n';
21826 PerfFile <<
AvHoursIntValue <<
" hours mean time betweeen train failures" <<
'\n';
21829 AnsiString AvLateMinsLocsNotReached =
"";
21835 if(LocsNotReached > 0)
21838 PerfFile << LocsNotReached <<
" locations that trains failed to reach (average lateness " << AvLateMinsLocsNotReached.c_str() <<
" min)" <<
'\n';
21842 PerfFile <<
SPADRisks <<
" SPAD risks" <<
'\n';
21846 PerfFile <<
SPADRisks <<
" SPAD risk" <<
'\n';
21858 PerfFile <<
Derailments <<
" derailments" <<
'\n';
21862 PerfFile <<
Derailments <<
" derailment" <<
'\n';
21872 PerfFile <<
'\n' <<
"***************************************" <<
'\n';
21874 bool DerailSPADFlag =
false, CrashFlag =
false;
21876 int OverallScorePercent = 100;
21877 int TotArrDepExit = 0;
21878 double TotLateMinsFactor = 1;
21879 double MissedStopAndSPADRiskFactor = 1;
21880 double NetNegFactor = 1;
21890 OverallScorePercent = 5;
21891 DerailSPADFlag =
true;
21895 OverallScorePercent = 0;
21898 if(OverallScorePercent == 100)
21903 LatenessPenalty = 0;
21909 if(TotArrDepExit > 0)
21918 NetNegFactor = TotLateMinsFactor * MissedStopAndSPADRiskFactor;
21920 OverallScorePercent = 100 * NetNegFactor;
21923 if((TotArrDepExit > 0) || DerailSPADFlag || CrashFlag)
21926 AnsiString OneFailureString =
", though the failure would account for some poor performance";
21927 AnsiString TwoOrMoreFailureString =
", though the failures would account for some poor performance";
21928 AnsiString AddedString =
"";
21931 AddedString = OneFailureString;
21935 AddedString = TwoOrMoreFailureString;
21937 PerfFile <<
"\nOverall score: " << OverallScorePercent <<
"%\n";
21938 AnsiString Rating =
"";
21939 if(OverallScorePercent == 100)
21941 Rating =
"Perfect!";
21943 else if(OverallScorePercent >= 95)
21945 Rating =
"Excellent";
21947 else if(OverallScorePercent >= 90)
21949 Rating =
"Very good";
21951 else if(OverallScorePercent >= 80)
21955 else if(OverallScorePercent >= 70)
21959 else if(OverallScorePercent >= 60)
21961 Rating =
"Unacceptable" + AddedString;
21963 else if(OverallScorePercent >= 50)
21965 Rating =
"Poor" + AddedString;
21967 else if(OverallScorePercent >= 40)
21969 Rating =
"Bad" + AddedString;
21971 else if(OverallScorePercent >= 30)
21973 Rating =
"Very bad" + AddedString;
21975 else if(OverallScorePercent >= 20)
21977 Rating =
"Terrible" + AddedString;
21979 else if(OverallScorePercent >= 10)
21981 Rating =
"Appalling" + AddedString;
21983 else if(OverallScorePercent >= 5)
21987 Rating =
"Disastrous - potential loss of life";
21992 Rating =
"Dire" + AddedString;
21995 else if(OverallScorePercent < 5)
21999 Rating =
"Catastrophic - loss of life";
22003 Rating =
"Abysmal";
22006 PerfFile <<
"Overall rating: " << Rating.c_str() <<
'\n';
22010 PerfFile <<
"\nThere were no timetabled departures, arrivals or exits so there is insufficient information to provide a performance score or rating" <<
'\n';
22012 PerfFile <<
'\n' <<
"***************************************";
22022 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
22072 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
22107 int IncrementalMinutes = 0;
22121 bool TrainOperatingFlag =
false;
22126 TrainOperatingFlag =
true;
22130 if(TrainOperatingFlag)
22138 for(
unsigned int z = 0; z < TDEntry.
ActionVector.size(); z++)
22185 AnsiString HeadCode;
22189 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
22193 HCandTrainPosParam.first = HeadCode;
22194 HCandTrainPosParam.second = TrainID;
22196 if((TimeToAct >= 0) && (TimeToAct < 59.9))
22199 OpTimeToActMultiMapEntry.first = TimeToAct;
22200 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
22229 float TimeToAct = 0;
22230 int DistanceToRedSignal = 0;
22233 ContinuationEntryVecPosVector.clear();
22234 bool LaterTrain =
false;
22238 LaterTrain =
false;
22239 if(CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry !=
NotStarted)
22250 if(!ContinuationEntryVecPosVector.empty())
22252 for(
unsigned int x = 0; x < ContinuationEntryVecPosVector.size(); x++)
22254 if(CTEIt->second.VectorPosition == ContinuationEntryVecPosVector.at(x))
22268 ContinuationEntryVecPosVector.push_back(CTEIt->second.VectorPosition);
22269 AnsiString HeadCode = CTEIt->second.HeadCode;
22270 float CurrentStopTime;
22271 float LaterStopTime;
22272 float RecoverableTime;
22275 int DistanceToExit;
22277 bool SigControlAndCanPassRedSignal =
false;
22285 if(CTEIt->second.TrainDataEntryPtr->ActionVector.size() == 1)
22291 SigControlAndCanPassRedSignal, &CTEIt->second.TrainDataEntryPtr->ActionVector.at(AtValue),
22292 HeadCode, TrainID, CurrentStopTime, LaterStopTime, RecoverableTime, AvTrackSpeed, DistanceToExit, ExitPair);
22295 if(AvTrackSpeed < 30)
22299 if(DistanceToRedSignal == -1)
22305 int Speed = AvTrackSpeed;
22306 int MaxSpeed = int(CTEIt->second.TrainDataEntryPtr->MaxRunningSpeed);
22307 if(AvTrackSpeed > MaxSpeed)
22311 if(CTEIt->second.TrainDataEntryPtr->ActionVector.at(0).SignallerControl)
22314 Speed = CTEIt->second.TrainDataEntryPtr->SignallerSpeed;
22317 TimeToAct = LaterStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
22322 float MinsBefEnter = double(CTEIt->first -
TTClockTime) * 86400.0 / 60.0;
22323 TimeToAct += MinsBefEnter;
22326 HCandTrainPosParam.first = HeadCode;
22327 HCandTrainPosParam.second = -1 - CTEIt->second.VectorPosition;
22330 if(TimeToAct < 59.9)
22332 OpTimeToActMultiMapEntry.first = TimeToAct;
22333 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
22358 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
22368 TimeToExitMultiMapEntry.first = ExitPair;
22369 TimeToExitMultiMapEntry.second = ExitInfo;
22379 bool SigControlAndCanPassRedSignal,
TActionVectorEntry *AVPtr, AnsiString HeadCode,
int TrainID,
float &CurrentStopTime,
float &LaterStopTime,
22380 float &RecoverableTime,
int &AvTrackSpeed,
int &DistanceToExit,
THVShortPair &ExitPair)
22389 AnsiString(TrackVectorPositionEntryPos) +
", " + AVPtr->
Command);
22390 int DistanceToRedSignal = 0;
22391 DistanceToExit = -1;
22392 ExitPair.first = -1;
22393 ExitPair.second = -1;
22394 int CumTrackSpeed = 0;
22396 int TrackSpeedCount = 0;
22397 float KmPerLocationStop;
22398 float MaxAllowableSpeed;
22408 int CurrentElement = TrackVectorPosition;
22409 int CurrentEntryPos = TrackVectorPositionEntryPos;
22414 CurrentStopTime = 0;
22416 RecoverableTime = 0;
22417 if(CurrentElement == -1)
22422 int CurrentExitPos;
22427 if((CurrentEntryPos == 0) || (CurrentEntryPos == 2))
22431 CurrentExitPos = 1;
22435 CurrentExitPos = 3;
22440 CurrentExitPos = 0;
22480 TimeToDepart+= 0.5;
22482 if(TimeToDepart < 0.5)
22484 TimeToDepart = 0.5;
22487 CurrentStopTime = float(TimeToDepart);
22495 CurrentStopTime = float(TimeToDepart);
22506 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
22517 else if(SigControlAndCanPassRedSignal)
22522 if((NextEntryPos == 0) || (NextEntryPos == 2))
22543 CurrentElement = NextElement;
22544 CurrentEntryPos = NextEntryPos;
22545 CurrentExitPos = NextExitPos;
22557 int LaterStopNumber = 0;
22561 while(!((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0)))
22570 if(CurrentEntryPos > 1)
22585 DistanceToExit = DistanceToRedSignal;
22590 if(TrackSpeedCount > 0)
22592 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
22596 if(CurrentEntryPos > 1)
22607 if(LaterStopNumber > 0)
22609 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
22610 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
22616 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
22620 if(AvTrackSpeed > MaxAllowableSpeed)
22622 AvTrackSpeed = MaxAllowableSpeed;
22634 bool StopRequired =
false;
22653 int TrainOnElement;
22660 if(CurrentEntryPos > 1)
22669 if((TrainOnElement > -1) && (TrainOnElement != TrainID))
22678 double StopTimeDouble;
22691 if(StopTimeDouble < 0.5)
22693 StopTimeDouble = 0.5;
22697 LaterStopTime += float(StopTimeDouble);
22698 RecoverableTime += StopTimeDouble - 0.5;
22699 if((LaterStopNumber == 1) && (TrainID > -1))
22707 if((AVPtr + 1)->FormatType ==
TimeLoc)
22711 StopTimeDouble = double((AVPtr + 1)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
22722 if(StopTimeDouble < 0.5)
22724 StopTimeDouble = 0.5;
22727 LaterStopTime += float(StopTimeDouble);
22728 RecoverableTime += StopTimeDouble - 0.5;
22729 if((LaterStopNumber == 1) && (TrainID > -1))
22739 StopTimeDouble = double((AVPtr + 2)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
22750 if(StopTimeDouble < 0.5)
22752 StopTimeDouble = 0.5;
22755 LaterStopTime += float(StopTimeDouble);
22756 RecoverableTime += StopTimeDouble - 0.5;
22757 if((LaterStopNumber == 1) && (TrainID > -1))
22774 if(NextElement == -1)
22783 if((NextEntryPos == 0) || (NextEntryPos == 2))
22804 CurrentElement = NextElement;
22805 CurrentEntryPos = NextEntryPos;
22806 CurrentExitPos = NextExitPos;
22811 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
22824 if(TrackSpeedCount > 0)
22826 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
22830 if(CurrentEntryPos > 1)
22841 if(LaterStopNumber > 0)
22843 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
22844 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
22850 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
22854 if(AvTrackSpeed > MaxAllowableSpeed)
22856 AvTrackSpeed = MaxAllowableSpeed;
22859 return(DistanceToRedSignal);